From ac712773098ec6ac923d150d434d1c8a9c54fc33 Mon Sep 17 00:00:00 2001 From: Manu Dhundi Date: Thu, 4 Apr 2024 09:11:26 -0700 Subject: [PATCH 01/36] Change Payload.len() and Payload.empty() to indicate actual payload size instead of max_txns_to_execute (#12696) * Change Payload.len() and Payload.empty() to indicate actual payload size instead of max_txns_to_execute * Address comments --- consensus/consensus-types/src/common.rs | 38 ++++++------------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/consensus/consensus-types/src/common.rs b/consensus/consensus-types/src/common.rs index 7d454aad5292c..b4522a84761cb 100644 --- a/consensus/consensus-types/src/common.rs +++ b/consensus/consensus-types/src/common.rs @@ -18,7 +18,7 @@ use aptos_types::{ use once_cell::sync::OnceCell; use rayon::prelude::*; use serde::{Deserialize, Serialize}; -use std::{cmp::min, collections::HashSet, fmt, fmt::Write, sync::Arc}; +use std::{collections::HashSet, fmt, fmt::Write, sync::Arc}; use tokio::sync::oneshot; /// The round of a block is a consensus-internal counter, which starts with 0 and increases @@ -255,28 +255,16 @@ impl Payload { Payload::DirectMempool(txns) => txns.len(), Payload::InQuorumStore(proof_with_status) => proof_with_status.len(), Payload::InQuorumStoreWithLimit(proof_with_status) => { - let num_txns = proof_with_status.proof_with_data.len(); - if proof_with_status.max_txns_to_execute.is_some() { - min(proof_with_status.max_txns_to_execute.unwrap(), num_txns) - } else { - num_txns - } + // here we return the actual length of the payload; limit is considered at the stage + // where we prepare the block from the payload + proof_with_status.proof_with_data.len() }, - Payload::QuorumStoreInlineHybrid( - inline_batches, - proof_with_data, - max_txns_to_execute, - ) => { - let num_txns = proof_with_data.len() + Payload::QuorumStoreInlineHybrid(inline_batches, proof_with_data, _) => { + proof_with_data.len() + inline_batches .iter() .map(|(_, txns)| txns.len()) - .sum::(); - if max_txns_to_execute.is_some() { - min(max_txns_to_execute.unwrap(), num_txns) - } else { - num_txns - } + .sum::() }, } } @@ -287,15 +275,9 @@ impl Payload { Payload::InQuorumStore(proof_with_status) => proof_with_status.proofs.is_empty(), Payload::InQuorumStoreWithLimit(proof_with_status) => { proof_with_status.proof_with_data.proofs.is_empty() - || proof_with_status.max_txns_to_execute == Some(0) }, - Payload::QuorumStoreInlineHybrid( - inline_batches, - proof_with_data, - max_txns_to_execute, - ) => { - *max_txns_to_execute == Some(0) - || (proof_with_data.proofs.is_empty() && inline_batches.is_empty()) + Payload::QuorumStoreInlineHybrid(inline_batches, proof_with_data, _) => { + proof_with_data.proofs.is_empty() && inline_batches.is_empty() }, } } @@ -371,8 +353,6 @@ impl Payload { .map(|txn| txn.raw_txn_bytes_len()) .sum(), Payload::InQuorumStore(proof_with_status) => proof_with_status.num_bytes(), - // We dedeup, shuffle and finally truncate the txns in the payload to the length == 'max_txns_to_execute'. - // Hence, it makes sense to pass the full size of the payload here. Payload::InQuorumStoreWithLimit(proof_with_status) => { proof_with_status.proof_with_data.num_bytes() }, From 1909d543dc45e5550cdf4b6b96ee89a2bfdbdfc4 Mon Sep 17 00:00:00 2001 From: aldenhu Date: Wed, 3 Apr 2024 18:40:23 +0000 Subject: [PATCH 02/36] gas profiler: group ledger writes --- .gitignore | 1 + aptos-move/aptos-gas-profiling/src/erased.rs | 26 +++++++++++-------- .../aptos-gas-profiling/src/flamegraph.rs | 13 +++++++--- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 9d63be8fc37a6..47156ef12d9ac 100644 --- a/.gitignore +++ b/.gitignore @@ -120,6 +120,7 @@ aptos-move/aptos-vm-profiling/**/*.txt # Gas profiler outputs aptos-move/e2e-move-tests/gas-profiling +gas-profiling # replay-verify and module-verify script outputs metadata-cache diff --git a/aptos-move/aptos-gas-profiling/src/erased.rs b/aptos-move/aptos-gas-profiling/src/erased.rs index 00d412889da7e..b59547af47bea 100644 --- a/aptos-move/aptos-gas-profiling/src/erased.rs +++ b/aptos-move/aptos-gas-profiling/src/erased.rs @@ -228,30 +228,34 @@ impl ExecutionAndIOCosts { nodes.push(self.call_graph.to_erased()); - nodes.push(Node::new( + nodes.push(self.ledger_writes()); + + TypeErasedExecutionAndIoCosts { + gas_scaling_factor: self.gas_scaling_factor, + total: self.total, + tree: Node::new_with_children("execution & IO (gas unit, full trace)", 0, nodes), + } + } + + fn ledger_writes(&self) -> Node { + let transaction = Node::new( "transaction", self.transaction_transient.unwrap_or_else(|| 0.into()), - )); + ); let events = Node::new_with_children( "events", 0, self.events_transient.iter().map(|event| event.to_erased()), ); - nodes.push(events); - let writes = Node::new_with_children( - "writes", + let write_ops = Node::new_with_children( + "state write ops", 0, self.write_set_transient .iter() .map(|write| write.to_erased()), ); - nodes.push(writes); - TypeErasedExecutionAndIoCosts { - gas_scaling_factor: self.gas_scaling_factor, - total: self.total, - tree: Node::new_with_children("execution & IO (gas unit, full trace)", 0, nodes), - } + Node::new_with_children("ledger writes", 0, vec![transaction, events, write_ops]) } } diff --git a/aptos-move/aptos-gas-profiling/src/flamegraph.rs b/aptos-move/aptos-gas-profiling/src/flamegraph.rs index ac342229186a4..c7e3fb6c7e99c 100644 --- a/aptos-move/aptos-gas-profiling/src/flamegraph.rs +++ b/aptos-move/aptos-gas-profiling/src/flamegraph.rs @@ -168,14 +168,21 @@ impl ExecutionAndIOCosts { .visit(&self.call_graph); if let Some(cost) = &self.transaction_transient { - lines.push("transaction_size", *cost) + lines.push("ledger_writes;transaction", *cost) } for item in &self.events_transient { - lines.push(format!("event_emits;<{}>", Render(&item.ty)), item.cost) + lines.push( + format!("ledger_writes;events;{}", Render(&item.ty)), + item.cost, + ) } for item in &self.write_set_transient { lines.push( - format!("write_set;{}<{}>", Render(&item.op_type), Render(&item.key)), + format!( + "ledger_writes;state_write_ops;{}<{}>", + Render(&item.op_type), + Render(&item.key) + ), item.cost, ) } From cdba8dd47d44752db0b6040f424fc38bab11e5e5 Mon Sep 17 00:00:00 2001 From: aldenhu Date: Wed, 3 Apr 2024 20:55:37 +0000 Subject: [PATCH 03/36] gas profiler: expose io write gas for transaction and events in the tables --- aptos-move/aptos-gas-profiling/src/report.rs | 18 +++++ .../aptos-gas-profiling/templates/index.html | 79 +++++++++++++------ 2 files changed, 75 insertions(+), 22 deletions(-) diff --git a/aptos-move/aptos-gas-profiling/src/report.rs b/aptos-move/aptos-gas-profiling/src/report.rs index 62ac8f3b02d80..60ccf1934c97b 100644 --- a/aptos-move/aptos-gas-profiling/src/report.rs +++ b/aptos-move/aptos-gas-profiling/src/report.rs @@ -179,6 +179,24 @@ impl TransactionGasLog { .collect(), ), ); + data.insert( + "transaction_write".to_string(), + convert_op(( + "transaction_write".to_string(), + 1, + aggregated.transaction_write, + )), + ); + data.insert( + "event_writes".to_string(), + Value::Array( + aggregated + .event_writes + .into_iter() + .map(convert_op) + .collect(), + ), + ); // Storage fee for the transaction itself let total_storage = u64::from(self.storage.total) as f64; diff --git a/aptos-move/aptos-gas-profiling/templates/index.html b/aptos-move/aptos-gas-profiling/templates/index.html index f1f4929a944f9..7b98da7ec0831 100644 --- a/aptos-move/aptos-gas-profiling/templates/index.html +++ b/aptos-move/aptos-gas-profiling/templates/index.html @@ -124,7 +124,7 @@

Execution

{{else}} (No operations to show.) {{/if}} -

Storage Reads

+

State Reads

{{#if reads}} @@ -145,27 +145,62 @@

Storage Reads

{{else}} (No reads to show.) {{/if}} -

Storage Writes

- {{#if writes}} -
- - - - - - - {{#each writes}} - - - - - - - {{/each}} -
Resource NameNumber of HitsCost in Gas UnitsPercentage
{{name}}{{hits}}{{cost}}{{percentage}}
- {{else}} - (No writes to show.) - {{/if}} +

Ledger Writes

+
Transaction Itself
+ + + + + + {{#with transaction_write}} + + + + + {{/with}} +
Cost in Gas UnitsPercentage
{{cost}}{{percentage}}
+
Events
+ {{#if event_writes}} + + + + + + + + {{#each event_writes}} + + + + + + + {{/each}} +
Event TypeNumber of HitsCost in Gas UnitsPercentage
{{name}}{{hits}}{{cost}}{{percentage}}
+ {{else}} + (No writes to show.) + {{/if}} +
State Write Ops
+ {{#if writes}} + + + + + + + + {{#each writes}} + + + + + + + {{/each}} +
Resource NameNumber of HitsCost in Gas UnitsPercentage
{{name}}{{hits}}{{cost}}{{percentage}}
+ {{else}} + (No writes to show.) + {{/if}}

Storage

The storage fees cover the extended-term storage of states and events and are assessed at a fixed price in APT. From 219d461f7d4e0366bb802ac6282e6f0d8b7266ce Mon Sep 17 00:00:00 2001 From: Wolfgang Grieskamp Date: Thu, 4 Apr 2024 10:13:19 -0700 Subject: [PATCH 04/36] [compiler-v2] Introduce language version (#12784) * [compiler-v2] Introduce language version This introduces the concept of a language version and pipes it through the various layers of the stack, from aptos CLI down to compiler v2, prover, and transactional test framework. - The `LanguageVersion` resides in the new file in the Move model, `metadata.rs`. The `CompilerVersion` has been also moved from the package system into there. Compiler and language version support formatting and parsing. They also support their default being populated from env vars `MOVE_COMPILER_V2` and `MOVE_LANGUAGE_V2`, respectively. - There is also a new data structure `CompilationMetadata` which we can use to attach to the file format metadata section in subsequent PRs. - Both compiler and language version have a qualifier whether a particular version is 'stable'. The value of this is populated in `CompilationMetadata` so we can perform run time checks and disallow an unstable version on production chains (subsequent PRs). - The aptos cli will print out a warning if an unstable compiler or language version is used. - The language version is attached to the GlobalEnv. The expression builder will refuse to build language constructs not supported by a given language version. - File format generator will not generate access specifiers if language v2 is not selected or if a special new experiment GEN_ACCESS_SPECIFIERS is on. This mitigates #12623 for now so we can lower priority but does not close it. - The acquires checks have been adapted to use the language version in the exp_builder instead of the previous flag. - A new test directory `checking-lang-v1` has been created to contain tests checking for disallowed v2 language features; some acquires related tests have been move there as well. * Addressing reviewer comments --- Cargo.lock | 6 + .../aptos-e2e-comparison-testing/Cargo.toml | 1 + .../src/execution.rs | 4 +- .../aptos-e2e-comparison-testing/src/lib.rs | 6 +- .../Cargo.toml | 7 +- .../tests/tests.rs | 2 + aptos-move/e2e-move-tests/Cargo.toml | 1 + aptos-move/e2e-move-tests/src/lib.rs | 7 +- aptos-move/framework/src/aptos.rs | 1 + aptos-move/framework/src/built_package.rs | 53 +++- aptos-move/framework/src/prover.rs | 4 +- .../framework/tests/move_prover_tests.rs | 1 + aptos-move/framework/tests/move_unit_test.rs | 5 +- crates/aptos/Cargo.toml | 1 + crates/aptos/src/common/types.rs | 11 +- crates/aptos/src/governance/mod.rs | 1 + crates/aptos/src/move_tool/mod.rs | 18 +- crates/aptos/src/move_tool/show.rs | 1 + crates/aptos/src/test/mod.rs | 1 + .../move-compiler-v2/src/acquires_checker.rs | 8 +- .../move/move-compiler-v2/src/experiments.rs | 8 + .../file_format_generator/module_generator.rs | 56 ++++- third_party/move/move-compiler-v2/src/lib.rs | 2 +- .../move/move-compiler-v2/src/options.rs | 12 + .../tests/acquires-checker/access_ok.exp | 91 ------- .../tests/checking-lang-v1/access_ok.exp | 139 +++++++++++ .../access_ok.move | 0 .../conditional_global_operations.exp | 26 +- .../conditional_global_operations.move | 0 .../invalid_type_acquire.exp | 20 +- .../invalid_type_acquire.move | 0 .../tests/checking-lang-v1/receiver_calls.exp | 25 ++ .../checking-lang-v1/receiver_calls.move | 29 +++ .../move/move-compiler-v2/tests/testsuite.rs | 19 +- .../transactional-tests/Cargo.toml | 1 + .../transactional-tests/tests/tests.rs | 22 +- .../move-model/src/builder/exp_builder.rs | 108 ++++---- third_party/move/move-model/src/lib.rs | 7 +- third_party/move/move-model/src/metadata.rs | 230 ++++++++++++++++++ third_party/move/move-model/src/model.rs | 16 +- third_party/move/move-model/src/options.rs | 11 +- third_party/move/move-prover/src/cli.rs | 19 +- third_party/move/move-prover/src/lib.rs | 1 + .../transactional-test-runner/Cargo.toml | 1 + .../src/framework.rs | 47 +++- .../src/vm_test_harness.rs | 11 +- .../move/tools/move-cli/src/base/docgen.rs | 9 +- .../move/tools/move-cli/src/base/errmap.rs | 4 +- .../move/tools/move-cli/src/base/prove.rs | 2 + .../src/compilation/compiled_package.rs | 7 +- .../src/compilation/model_builder.rs | 7 +- .../move/tools/move-package/src/lib.rs | 32 +-- .../tools/move-package/tests/test_runner.rs | 6 +- .../compilation/basic_no_deps/Move.exp | 1 + .../basic_no_deps_address_assigned/Move.exp | 1 + .../Move.exp | 1 + .../basic_no_deps_test_mode/Move.exp | 1 + .../Move.exp | 1 + .../diamond_problem_no_conflict/Move.exp | 1 + .../compilation/multiple_deps_rename/Move.exp | 1 + .../multiple_deps_rename_one/Move.exp | 1 + .../test_sources/compilation/one_dep/Move.exp | 1 + .../one_dep_assigned_address/Move.exp | 1 + .../compilation/one_dep_renamed/Move.exp | 1 + .../compilation/one_dep_with_scripts/Move.exp | 1 + .../compilation/test_symlinks/Move.exp | 1 + .../invalid_identifier_package_name/Move.exp | 1 + .../parsing/minimal_manifest/Move.exp | 1 + .../resolution/basic_no_deps/Move.exp | 1 + .../basic_no_deps_address_assigned/Move.exp | 1 + .../Move.exp | 1 + .../resolution/dep_good_digest/Move.exp | 1 + .../Move.exp | 1 + .../diamond_problem_no_conflict/Move.exp | 1 + .../resolution/multiple_deps_rename/Move.exp | 1 + .../test_sources/resolution/one_dep/Move.exp | 1 + .../one_dep_assigned_address/Move.exp | 1 + .../one_dep_multiple_of_same_name/Move.exp | 1 + .../one_dep_reassigned_address/Move.exp | 1 + .../Move.exp | 1 + 80 files changed, 878 insertions(+), 256 deletions(-) delete mode 100644 third_party/move/move-compiler-v2/tests/acquires-checker/access_ok.exp create mode 100644 third_party/move/move-compiler-v2/tests/checking-lang-v1/access_ok.exp rename third_party/move/move-compiler-v2/tests/{acquires-checker => checking-lang-v1}/access_ok.move (100%) rename third_party/move/move-compiler-v2/tests/{acquires-checker => checking-lang-v1}/conditional_global_operations.exp (73%) rename third_party/move/move-compiler-v2/tests/{acquires-checker => checking-lang-v1}/conditional_global_operations.move (100%) rename third_party/move/move-compiler-v2/tests/{acquires-checker/v1-tests => checking-lang-v1}/invalid_type_acquire.exp (52%) rename third_party/move/move-compiler-v2/tests/{acquires-checker/v1-tests => checking-lang-v1}/invalid_type_acquire.move (100%) create mode 100644 third_party/move/move-compiler-v2/tests/checking-lang-v1/receiver_calls.exp create mode 100644 third_party/move/move-compiler-v2/tests/checking-lang-v1/receiver_calls.move create mode 100644 third_party/move/move-model/src/metadata.rs diff --git a/Cargo.lock b/Cargo.lock index 4789cb16e365f..ddc50b4f8bdc7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -289,6 +289,7 @@ dependencies = [ "move-coverage", "move-disassembler", "move-ir-types", + "move-model", "move-package", "move-symbol-pool", "move-unit-test", @@ -764,6 +765,7 @@ dependencies = [ "itertools 0.12.1", "move-compiler", "move-core-types", + "move-model", "move-package", "rocksdb", "serde", @@ -3901,6 +3903,7 @@ dependencies = [ "move-command-line-common", "move-compiler", "move-core-types", + "move-model", "move-resource-viewer", "move-transactional-test-runner", "move-vm-runtime", @@ -6964,6 +6967,7 @@ dependencies = [ "move-binary-format", "move-command-line-common", "move-core-types", + "move-model", "move-package", "move-symbol-pool", "once_cell", @@ -10417,6 +10421,7 @@ dependencies = [ "itertools 0.10.5", "move-command-line-common", "move-compiler-v2", + "move-model", "move-transactional-test-runner", "once_cell", "walkdir", @@ -10915,6 +10920,7 @@ dependencies = [ "move-disassembler", "move-ir-compiler", "move-ir-types", + "move-model", "move-resource-viewer", "move-stdlib", "move-symbol-pool", diff --git a/aptos-move/aptos-e2e-comparison-testing/Cargo.toml b/aptos-move/aptos-e2e-comparison-testing/Cargo.toml index fa365a0a44ae6..e28cf89d1a5d4 100644 --- a/aptos-move/aptos-e2e-comparison-testing/Cargo.toml +++ b/aptos-move/aptos-e2e-comparison-testing/Cargo.toml @@ -24,6 +24,7 @@ futures = { workspace = true } itertools = { workspace = true } move-compiler = { workspace = true } move-core-types = { workspace = true } +move-model = { workspace = true } move-package = { workspace = true } rocksdb = { workspace = true } serde = { workspace = true } diff --git a/aptos-move/aptos-e2e-comparison-testing/src/execution.rs b/aptos-move/aptos-e2e-comparison-testing/src/execution.rs index 0e8d84ec9d2e2..9e85437fce474 100644 --- a/aptos-move/aptos-e2e-comparison-testing/src/execution.rs +++ b/aptos-move/aptos-e2e-comparison-testing/src/execution.rs @@ -21,7 +21,7 @@ use aptos_vm::data_cache::AsMoveResolver; use clap::ValueEnum; use itertools::Itertools; use move_core_types::{account_address::AccountAddress, language_storage::ModuleId}; -use move_package::CompilerVersion; +use move_model::metadata::CompilerVersion; use std::{cmp, collections::HashMap, path::PathBuf, sync::Arc}; fn load_packages_to_executor( @@ -222,7 +222,7 @@ impl Execution { v2_failed = true; } else { let compiled_res_v2 = - compile_package(package_dir, &package_info, Some(CompilerVersion::V2)); + compile_package(package_dir, &package_info, Some(CompilerVersion::V2_0)); if let Ok(compiled_res) = compiled_res_v2 { generate_compiled_blob( &package_info, diff --git a/aptos-move/aptos-e2e-comparison-testing/src/lib.rs b/aptos-move/aptos-e2e-comparison-testing/src/lib.rs index 18d295bbd2af3..9f672e517acc8 100644 --- a/aptos-move/aptos-e2e-comparison-testing/src/lib.rs +++ b/aptos-move/aptos-e2e-comparison-testing/src/lib.rs @@ -32,13 +32,13 @@ pub use data_collection::*; pub use execution::*; use move_compiler::compiled_unit::CompiledUnitEnum; use move_core_types::language_storage::ModuleId; +use move_model::metadata::CompilerVersion; use move_package::{ compilation::compiled_package::CompiledPackage, source_package::{ manifest_parser::{parse_move_manifest_string, parse_source_manifest}, parsed_manifest::Dependency, }, - CompilerVersion, }; pub use online_execution::*; @@ -414,7 +414,7 @@ fn compile_aptos_packages( for package in APTOS_PACKAGES { let root_package_dir = aptos_commons_path.join(get_aptos_dir(package).unwrap()); let compiler_version = if v2_flag { - Some(CompilerVersion::V2) + Some(CompilerVersion::V2_0) } else { Some(CompilerVersion::V1) }; @@ -580,7 +580,7 @@ fn dump_and_compile_from_package_metadata( } if execution_mode.is_some_and(|mode| mode.is_v2_or_compare()) { let package_v2 = - compile_package(root_package_dir, &package_info, Some(CompilerVersion::V2)); + compile_package(root_package_dir, &package_info, Some(CompilerVersion::V2_0)); if let Ok(built_package) = package_v2 { generate_compiled_blob( &package_info, diff --git a/aptos-move/aptos-transactional-test-harness/Cargo.toml b/aptos-move/aptos-transactional-test-harness/Cargo.toml index 2e89c0185fa7b..407e8a41d6a4f 100644 --- a/aptos-move/aptos-transactional-test-harness/Cargo.toml +++ b/aptos-move/aptos-transactional-test-harness/Cargo.toml @@ -21,17 +21,18 @@ aptos-framework = { workspace = true } aptos-gas-schedule = { workspace = true } aptos-language-e2e-tests = { workspace = true } aptos-storage-interface = { workspace = true } -aptos-types = { workspace = true, features = [ "fuzzing" ] } +aptos-types = { workspace = true, features = ["fuzzing"] } aptos-vm = { workspace = true } aptos-vm-genesis = { workspace = true } bcs = { workspace = true } clap = { workspace = true } hex = { workspace = true } -move-binary-format = { workspace = true, features = [ "fuzzing" ] } +move-binary-format = { workspace = true, features = ["fuzzing"] } move-bytecode-verifier = { workspace = true } move-command-line-common = { workspace = true } move-compiler = { workspace = true } -move-core-types = { workspace = true, features = [ "fuzzing" ] } +move-core-types = { workspace = true, features = ["fuzzing"] } +move-model = { workspace = true } move-resource-viewer = { workspace = true } move-transactional-test-runner = { workspace = true } move-vm-runtime = { workspace = true } diff --git a/aptos-move/aptos-transactional-test-harness/tests/tests.rs b/aptos-move/aptos-transactional-test-harness/tests/tests.rs index 250e5f8b03fb4..bf56ae5ac21db 100644 --- a/aptos-move/aptos-transactional-test-harness/tests/tests.rs +++ b/aptos-move/aptos-transactional-test-harness/tests/tests.rs @@ -3,6 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 use aptos_transactional_test_harness::run_aptos_test_with_config; +use move_model::metadata::LanguageVersion; use move_transactional_test_runner::vm_test_harness::TestRunConfig; use std::path::Path; @@ -13,6 +14,7 @@ fn runner(path: &Path) -> anyhow::Result<(), Box> { // TODO: we may later want to change this to comparison testing. For now we are mostly // interested in debugging v2 bytecode. run_aptos_test_with_config(path, TestRunConfig::CompilerV2 { + language_version: LanguageVersion::default(), v2_experiments: vec![], }) } else { diff --git a/aptos-move/e2e-move-tests/Cargo.toml b/aptos-move/e2e-move-tests/Cargo.toml index b675a5cdcd9ea..b795c55795071 100644 --- a/aptos-move/e2e-move-tests/Cargo.toml +++ b/aptos-move/e2e-move-tests/Cargo.toml @@ -30,6 +30,7 @@ hex = { workspace = true } move-binary-format = { workspace = true } move-command-line-common = { workspace = true } move-core-types = { workspace = true } +move-model = { workspace = true } move-package = { workspace = true } move-symbol-pool = { workspace = true } once_cell = { workspace = true } diff --git a/aptos-move/e2e-move-tests/src/lib.rs b/aptos-move/e2e-move-tests/src/lib.rs index 60e981d417daa..1ff4265e93433 100644 --- a/aptos-move/e2e-move-tests/src/lib.rs +++ b/aptos-move/e2e-move-tests/src/lib.rs @@ -13,9 +13,8 @@ use anyhow::bail; use aptos_framework::{BuildOptions, BuiltPackage, UPGRADE_POLICY_CUSTOM_FIELD}; pub use harness::*; use move_command_line_common::{env::read_bool_env_var, testing::MOVE_COMPILER_V2}; -use move_package::{ - package_hooks::PackageHooks, source_package::parsed_manifest::CustomDepInfo, CompilerVersion, -}; +use move_model::metadata::CompilerVersion; +use move_package::{package_hooks::PackageHooks, source_package::parsed_manifest::CustomDepInfo}; use move_symbol_pool::Symbol; pub use stake::*; use std::path::PathBuf; @@ -49,7 +48,7 @@ pub(crate) fn build_package( ) -> anyhow::Result { let mut options = options; if read_bool_env_var(MOVE_COMPILER_V2) { - options.compiler_version = Some(CompilerVersion::V2); + options.compiler_version = Some(CompilerVersion::V2_0); } BuiltPackage::build(package_path.to_owned(), options) } diff --git a/aptos-move/framework/src/aptos.rs b/aptos-move/framework/src/aptos.rs index b27745c8eb289..79e6c1e36f348 100644 --- a/aptos-move/framework/src/aptos.rs +++ b/aptos-move/framework/src/aptos.rs @@ -120,6 +120,7 @@ impl ReleaseTarget { skip_fetch_latest_git_deps: true, bytecode_version: None, compiler_version: None, + language_version: None, skip_attribute_checks: false, check_test_code: false, known_attributes: extended_checks::get_all_attribute_names().clone(), diff --git a/aptos-move/framework/src/built_package.rs b/aptos-move/framework/src/built_package.rs index c69610146b1f0..a6e6f90b97206 100644 --- a/aptos-move/framework/src/built_package.rs +++ b/aptos-move/framework/src/built_package.rs @@ -13,23 +13,26 @@ use aptos_types::{account_address::AccountAddress, transaction::EntryABI}; use clap::Parser; use codespan_reporting::{ diagnostic::Severity, - term::termcolor::{ColorChoice, StandardStream}, + term::termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}, }; use itertools::Itertools; use move_binary_format::CompiledModule; use move_command_line_common::files::MOVE_COMPILED_EXTENSION; use move_compiler::compiled_unit::{CompiledUnit, NamedCompiledModule}; use move_core_types::{language_storage::ModuleId, metadata::Metadata}; -use move_model::model::GlobalEnv; +use move_model::{ + metadata::{CompilerVersion, LanguageVersion}, + model::GlobalEnv, +}; use move_package::{ compilation::{compiled_package::CompiledPackage, package_layout::CompiledPackageLayout}, source_package::manifest_parser::{parse_move_manifest_string, parse_source_manifest}, - BuildConfig, CompilerConfig, CompilerVersion, ModelConfig, + BuildConfig, CompilerConfig, ModelConfig, }; use serde::{Deserialize, Serialize}; use std::{ collections::{BTreeMap, BTreeSet}, - io::stderr, + io::{stderr, Write}, path::{Path, PathBuf}, }; @@ -76,8 +79,10 @@ pub struct BuildOptions { pub skip_fetch_latest_git_deps: bool, #[clap(long)] pub bytecode_version: Option, - #[clap(long)] + #[clap(long, value_parser = clap::value_parser!(CompilerVersion))] pub compiler_version: Option, + #[clap(long, value_parser = clap::value_parser!(LanguageVersion))] + pub language_version: Option, #[clap(long)] pub skip_attribute_checks: bool, #[clap(long)] @@ -105,6 +110,7 @@ impl Default for BuildOptions { skip_fetch_latest_git_deps: false, bytecode_version: None, compiler_version: None, + language_version: None, skip_attribute_checks: false, check_test_code: false, known_attributes: extended_checks::get_all_attribute_names().clone(), @@ -127,6 +133,7 @@ pub fn build_model( target_filter: Option, bytecode_version: Option, compiler_version: Option, + language_version: Option, skip_attribute_checks: bool, known_attributes: BTreeSet, ) -> anyhow::Result { @@ -146,15 +153,19 @@ pub fn build_model( compiler_config: CompilerConfig { bytecode_version, compiler_version, + language_version, skip_attribute_checks, known_attributes, }, }; let compiler_version = compiler_version.unwrap_or_default(); + let language_version = language_version.unwrap_or_default(); + compiler_version.check_language_support(language_version)?; build_config.move_model_for_package(package_path, ModelConfig { target_filter, all_files_as_targets: false, compiler_version, + language_version, }) } @@ -166,6 +177,8 @@ impl BuiltPackage { pub fn build(package_path: PathBuf, options: BuildOptions) -> anyhow::Result { let bytecode_version = options.bytecode_version; let compiler_version = options.compiler_version; + let language_version = options.language_version; + Self::check_versions(&compiler_version, &language_version)?; let skip_attribute_checks = options.skip_attribute_checks; let build_config = BuildConfig { dev_mode: options.dev, @@ -183,6 +196,7 @@ impl BuiltPackage { compiler_config: CompilerConfig { bytecode_version, compiler_version, + language_version, skip_attribute_checks, known_attributes: options.known_attributes.clone(), }, @@ -250,6 +264,35 @@ impl BuiltPackage { }) } + // Check versions and warn user if using unstable ones. + fn check_versions( + compiler_version: &Option, + language_version: &Option, + ) -> anyhow::Result<()> { + let effective_compiler_version = compiler_version.unwrap_or_default(); + let effective_language_version = language_version.unwrap_or_default(); + let mut error_writer = StandardStream::stderr(ColorChoice::Auto); + error_writer.set_color(ColorSpec::new().set_fg(Some(Color::Yellow)))?; + if effective_compiler_version.unstable() { + writeln!( + &mut error_writer, + "Warning: compiler version `{}` is experimental \ + and should not be used in production", + effective_compiler_version + )? + } + if effective_language_version.unstable() { + writeln!( + &mut error_writer, + "Warning: language version `{}` is experimental \ + and should not be used in production", + effective_language_version + )? + } + effective_compiler_version.check_language_support(effective_language_version)?; + Ok(()) + } + /// Returns the name of this package. pub fn name(&self) -> &str { self.package.compiled_package_info.package_name.as_str() diff --git a/aptos-move/framework/src/prover.rs b/aptos-move/framework/src/prover.rs index 20adcad9e6b5c..5351388a66ad1 100644 --- a/aptos-move/framework/src/prover.rs +++ b/aptos-move/framework/src/prover.rs @@ -8,7 +8,7 @@ use codespan_reporting::{ }; use log::LevelFilter; use move_core_types::account_address::AccountAddress; -use move_package::CompilerVersion; +use move_model::metadata::{CompilerVersion, LanguageVersion}; use std::{ collections::{BTreeMap, BTreeSet}, path::Path, @@ -120,6 +120,7 @@ impl ProverOptions { named_addresses: BTreeMap, bytecode_version: Option, compiler_version: Option, + language_version: Option, skip_attribute_checks: bool, known_attributes: &BTreeSet, ) -> anyhow::Result<()> { @@ -132,6 +133,7 @@ impl ProverOptions { self.filter.clone(), bytecode_version, compiler_version, + language_version, skip_attribute_checks, known_attributes.clone(), )?; diff --git a/aptos-move/framework/tests/move_prover_tests.rs b/aptos-move/framework/tests/move_prover_tests.rs index defcf9e69b26c..466aea472db31 100644 --- a/aptos-move/framework/tests/move_prover_tests.rs +++ b/aptos-move/framework/tests/move_prover_tests.rs @@ -59,6 +59,7 @@ pub fn run_prover_for_pkg(path_to_pkg: impl Into) { BTreeMap::default(), None, None, + None, skip_attribute_checks, extended_checks::get_all_attribute_names(), ) diff --git a/aptos-move/framework/tests/move_unit_test.rs b/aptos-move/framework/tests/move_unit_test.rs index d33ee29ca673d..cc7e3a0003d28 100644 --- a/aptos-move/framework/tests/move_unit_test.rs +++ b/aptos-move/framework/tests/move_unit_test.rs @@ -10,7 +10,8 @@ use aptos_types::on_chain_config::{ use aptos_vm::natives; use move_cli::base::test::{run_move_unit_tests, UnitTestResult}; use move_command_line_common::{env::read_bool_env_var, testing::MOVE_COMPILER_V2}; -use move_package::{CompilerConfig, CompilerVersion}; +use move_model::metadata::CompilerVersion; +use move_package::CompilerConfig; use move_unit_test::UnitTestingConfig; use move_vm_runtime::native_functions::NativeFunctionTable; use tempfile::tempdir; @@ -46,7 +47,7 @@ fn run_tests_for_pkg(path_to_pkg: impl Into) { } if read_bool_env_var(MOVE_COMPILER_V2) { // Run test against v2 when MOVE_COMPILER_V2 is set - compiler_config.compiler_version = Some(CompilerVersion::V2); + compiler_config.compiler_version = Some(CompilerVersion::V2_0); build_config.compiler_config = compiler_config; ok = run_move_unit_tests( &pkg_path, diff --git a/crates/aptos/Cargo.toml b/crates/aptos/Cargo.toml index 1d3dcf61f65e6..f1e3820d602ec 100644 --- a/crates/aptos/Cargo.toml +++ b/crates/aptos/Cargo.toml @@ -72,6 +72,7 @@ move-core-types = { workspace = true } move-coverage = { workspace = true } move-disassembler = { workspace = true } move-ir-types = { workspace = true } +move-model = { workspace = true } move-package = { workspace = true } move-symbol-pool = { workspace = true } move-unit-test = { workspace = true, features = ["debugging"] } diff --git a/crates/aptos/src/common/types.rs b/crates/aptos/src/common/types.rs index c990a2d4df2ca..713d700994e7c 100644 --- a/crates/aptos/src/common/types.rs +++ b/crates/aptos/src/common/types.rs @@ -48,7 +48,7 @@ use async_trait::async_trait; use clap::{Parser, ValueEnum}; use hex::FromHexError; use move_core_types::{account_address::AccountAddress, language_storage::TypeTag}; -use move_package::CompilerVersion; +use move_model::metadata::{CompilerVersion, LanguageVersion}; use serde::{Deserialize, Serialize}; #[cfg(unix)] use std::os::unix::fs::OpenOptionsExt; @@ -1059,9 +1059,15 @@ pub struct MovePackageDir { /// Specify the version of the compiler. /// /// Currently hidden until the official launch of Compiler V2 - #[clap(long, hide = true)] + #[clap(long, hide = true, value_parser = clap::value_parser!(CompilerVersion))] pub compiler_version: Option, + /// Specify the language version to be supported. + /// + /// Currently hidden until the official launch of Compiler V2 + #[clap(long, hide = true, value_parser = clap::value_parser!(LanguageVersion))] + pub language_version: Option, + /// Do not complain about unknown attributes in Move code. #[clap(long)] pub skip_attribute_checks: bool, @@ -1083,6 +1089,7 @@ impl MovePackageDir { skip_fetch_latest_git_deps: true, bytecode_version: None, compiler_version: None, + language_version: None, skip_attribute_checks: false, check_test_code: false, } diff --git a/crates/aptos/src/governance/mod.rs b/crates/aptos/src/governance/mod.rs index a781f12dbee32..d103f4b4e7d86 100644 --- a/crates/aptos/src/governance/mod.rs +++ b/crates/aptos/src/governance/mod.rs @@ -997,6 +997,7 @@ impl CliCommand<()> for GenerateUpgradeProposal { move_options.named_addresses(), move_options.bytecode_version, move_options.compiler_version, + move_options.language_version, move_options.skip_attribute_checks, move_options.check_test_code, ); diff --git a/crates/aptos/src/move_tool/mod.rs b/crates/aptos/src/move_tool/mod.rs index 899d11cdf4f4e..b1db6deefd5e6 100644 --- a/crates/aptos/src/move_tool/mod.rs +++ b/crates/aptos/src/move_tool/mod.rs @@ -45,9 +45,8 @@ use itertools::Itertools; use move_cli::{self, base::test::UnitTestResult}; use move_command_line_common::env::MOVE_HOME; use move_core_types::{identifier::Identifier, language_storage::ModuleId, u256::U256}; -use move_package::{ - source_package::layout::SourcePackageLayout, BuildConfig, CompilerConfig, CompilerVersion, -}; +use move_model::metadata::{CompilerVersion, LanguageVersion}; +use move_package::{source_package::layout::SourcePackageLayout, BuildConfig, CompilerConfig}; use move_unit_test::UnitTestingConfig; pub use package_hooks::*; use serde::{Deserialize, Serialize}; @@ -327,6 +326,7 @@ impl CliCommand> for CompilePackage { self.move_options.named_addresses(), self.move_options.bytecode_version, self.move_options.compiler_version, + self.move_options.language_version, self.move_options.skip_attribute_checks, self.move_options.check_test_code, ) @@ -389,6 +389,7 @@ impl CompileScript { self.move_options.named_addresses(), self.move_options.bytecode_version, self.move_options.compiler_version, + self.move_options.language_version, self.move_options.skip_attribute_checks, self.move_options.check_test_code, ) @@ -557,6 +558,7 @@ impl CliCommand<&'static str> for ProvePackage { move_options.named_addresses(), move_options.bytecode_version, move_options.compiler_version, + move_options.language_version, move_options.skip_attribute_checks, extended_checks::get_all_attribute_names(), ) @@ -606,6 +608,7 @@ impl CliCommand<&'static str> for DocumentPackage { skip_fetch_latest_git_deps: move_options.skip_fetch_latest_git_deps, bytecode_version: move_options.bytecode_version, compiler_version: move_options.compiler_version, + language_version: move_options.language_version, skip_attribute_checks: move_options.skip_attribute_checks, check_test_code: move_options.check_test_code, known_attributes: extended_checks::get_all_attribute_names().clone(), @@ -674,6 +677,7 @@ impl TryInto for &PublishPackage { self.move_options.named_addresses(), self.move_options.bytecode_version, self.move_options.compiler_version, + self.move_options.language_version, self.move_options.skip_attribute_checks, self.move_options.check_test_code, ); @@ -744,6 +748,7 @@ impl IncludedArtifacts { named_addresses: BTreeMap, bytecode_version: Option, compiler_version: Option, + language_version: Option, skip_attribute_checks: bool, check_test_code: bool, ) -> BuildOptions { @@ -760,6 +765,7 @@ impl IncludedArtifacts { skip_fetch_latest_git_deps, bytecode_version, compiler_version, + language_version, skip_attribute_checks, check_test_code, known_attributes: extended_checks::get_all_attribute_names().clone(), @@ -775,6 +781,7 @@ impl IncludedArtifacts { skip_fetch_latest_git_deps, bytecode_version, compiler_version, + language_version, skip_attribute_checks, check_test_code, known_attributes: extended_checks::get_all_attribute_names().clone(), @@ -790,6 +797,7 @@ impl IncludedArtifacts { skip_fetch_latest_git_deps, bytecode_version, compiler_version, + language_version, skip_attribute_checks, check_test_code, known_attributes: extended_checks::get_all_attribute_names().clone(), @@ -910,6 +918,7 @@ impl CliCommand for CreateObjectAndPublishPackage { self.move_options.named_addresses(), self.move_options.bytecode_version, self.move_options.compiler_version, + self.move_options.language_version, self.move_options.skip_attribute_checks, self.move_options.check_test_code, ); @@ -986,6 +995,7 @@ impl CliCommand for UpgradeObjectPackage { self.move_options.named_addresses(), self.move_options.bytecode_version, self.move_options.compiler_version, + self.move_options.language_version, self.move_options.skip_attribute_checks, self.move_options.check_test_code, ); @@ -1110,6 +1120,7 @@ impl CliCommand for CreateResourceAccountAndPublishPackage { move_options.named_addresses(), move_options.bytecode_version, move_options.compiler_version, + move_options.language_version, move_options.skip_attribute_checks, move_options.check_test_code, ); @@ -1261,6 +1272,7 @@ impl CliCommand<&'static str> for VerifyPackage { self.move_options.named_addresses(), self.move_options.bytecode_version, self.move_options.compiler_version, + self.move_options.language_version, self.move_options.skip_attribute_checks, self.move_options.check_test_code, ) diff --git a/crates/aptos/src/move_tool/show.rs b/crates/aptos/src/move_tool/show.rs index 22e49f0848a3c..bb763334dab60 100644 --- a/crates/aptos/src/move_tool/show.rs +++ b/crates/aptos/src/move_tool/show.rs @@ -65,6 +65,7 @@ impl CliCommand> for ShowAbi { self.move_options.named_addresses(), self.move_options.bytecode_version, self.move_options.compiler_version, + self.move_options.language_version, self.move_options.skip_attribute_checks, self.move_options.check_test_code, ) diff --git a/crates/aptos/src/test/mod.rs b/crates/aptos/src/test/mod.rs index 28cac8a33f1e3..405877e62a54b 100644 --- a/crates/aptos/src/test/mod.rs +++ b/crates/aptos/src/test/mod.rs @@ -1058,6 +1058,7 @@ impl CliTestFramework { skip_fetch_latest_git_deps: true, bytecode_version: None, compiler_version: None, + language_version: None, skip_attribute_checks: false, check_test_code: false, } diff --git a/third_party/move/move-compiler-v2/src/acquires_checker.rs b/third_party/move/move-compiler-v2/src/acquires_checker.rs index e58208eb48c65..6894f9703ffed 100644 --- a/third_party/move/move-compiler-v2/src/acquires_checker.rs +++ b/third_party/move/move-compiler-v2/src/acquires_checker.rs @@ -6,7 +6,7 @@ //! - The body of `m::f` contains a `move_from`, `borrow_global_mut`, or `borrow_global` instruction, or //! - The body of `m::f` invokes a function `m::g` declared in the same module that is annotated with acquires //! Warn if access specifiers other than plain `acquires R` is used. -//! This check is enabled by flag `Experiment::ACQUIRES_CHECK`, and is disabled by default. +//! This check is enabled by flag `Experiment::ACQUIRES_CHECK`. use move_model::{ ast::{ExpData, Operation, ResourceSpecifier, VisitorPosition}, @@ -63,7 +63,7 @@ fn get_acquired_resources(fun_env: &FunctionEnv) -> BTreeMap { if let Some(access_specifiers) = fun_env.get_access_specifiers() { access_specifiers .iter() - .map(|access_specifier| { + .filter_map(|access_specifier| { if let ResourceSpecifier::Resource(inst_qid) = &access_specifier.resource.1 { if inst_qid.module_id != fun_env.module_env.get_id() { fun_env.module_env.env.error( @@ -71,9 +71,9 @@ fn get_acquired_resources(fun_env: &FunctionEnv) -> BTreeMap { "acquires a resource from another module", ) } - (inst_qid.id, access_specifier.resource.0.clone()) + Some((inst_qid.id, access_specifier.resource.0.clone())) } else { - unreachable!("unexpected resource specifier") + None } }) .collect() diff --git a/third_party/move/move-compiler-v2/src/experiments.rs b/third_party/move/move-compiler-v2/src/experiments.rs index 00ca886a0b82b..cc79a1c8158ef 100644 --- a/third_party/move/move-compiler-v2/src/experiments.rs +++ b/third_party/move/move-compiler-v2/src/experiments.rs @@ -159,6 +159,13 @@ pub static EXPERIMENTS: Lazy> = Lazy::new(|| { .to_string(), default: Given(false), }, + Experiment { + name: Experiment::GEN_ACCESS_SPECIFIERS.to_string(), + description: "Whether to generate access specifiers in the file format.\ + This is currently off by default to mitigate bug #12623." + .to_string(), + default: Given(false), + }, ]; experiments .into_iter() @@ -176,6 +183,7 @@ impl Experiment { pub const CHECKS: &'static str = "checks"; pub const COPY_PROPAGATION: &'static str = "copy-propagation"; pub const DEAD_CODE_ELIMINATION: &'static str = "dead-code-elimination"; + pub const GEN_ACCESS_SPECIFIERS: &'static str = "gen-access-specifiers"; pub const INLINING: &'static str = "inlining"; pub const KEEP_INLINE_FUNS: &'static str = "keep-inline-funs"; pub const KEEP_UNINIT_ANNOTATIONS: &'static str = "keep-uninit-annotations"; diff --git a/third_party/move/move-compiler-v2/src/file_format_generator/module_generator.rs b/third_party/move/move-compiler-v2/src/file_format_generator/module_generator.rs index c360effe79004..d56ad9d498a5c 100644 --- a/third_party/move/move-compiler-v2/src/file_format_generator/module_generator.rs +++ b/third_party/move/move-compiler-v2/src/file_format_generator/module_generator.rs @@ -1,16 +1,19 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use crate::file_format_generator::{ - function_generator::FunctionGenerator, MAX_ADDRESS_COUNT, MAX_CONST_COUNT, MAX_FIELD_COUNT, - MAX_FIELD_INST_COUNT, MAX_FUNCTION_COUNT, MAX_FUNCTION_INST_COUNT, MAX_IDENTIFIER_COUNT, - MAX_MODULE_COUNT, MAX_SIGNATURE_COUNT, MAX_STRUCT_COUNT, MAX_STRUCT_DEF_COUNT, - MAX_STRUCT_DEF_INST_COUNT, +use crate::{ + file_format_generator::{ + function_generator::FunctionGenerator, MAX_ADDRESS_COUNT, MAX_CONST_COUNT, MAX_FIELD_COUNT, + MAX_FIELD_INST_COUNT, MAX_FUNCTION_COUNT, MAX_FUNCTION_INST_COUNT, MAX_IDENTIFIER_COUNT, + MAX_MODULE_COUNT, MAX_SIGNATURE_COUNT, MAX_STRUCT_COUNT, MAX_STRUCT_DEF_COUNT, + MAX_STRUCT_DEF_INST_COUNT, + }, + Experiment, Options, }; use codespan_reporting::diagnostic::Severity; use move_binary_format::{ file_format as FF, - file_format::{FunctionHandle, ModuleHandle, StructDefinitionIndex, TableIndex}, + file_format::{AccessKind, FunctionHandle, ModuleHandle, StructDefinitionIndex, TableIndex}, file_format_common, }; use move_bytecode_source_map::source_map::{SourceMap, SourceName}; @@ -18,6 +21,7 @@ use move_core_types::{account_address::AccountAddress, identifier::Identifier}; use move_ir_types::ast as IR_AST; use move_model::{ ast::{AccessSpecifier, Address, AddressSpecifier, ResourceSpecifier}, + metadata::LanguageVersion, model::{ FieldEnv, FunId, FunctionEnv, GlobalEnv, Loc, ModuleEnv, ModuleId, Parameter, QualifiedId, StructEnv, StructId, TypeParameter, TypeParameterKind, @@ -35,6 +39,8 @@ use std::collections::{BTreeMap, BTreeSet}; /// Internal state of the module code generator #[derive(Debug)] pub struct ModuleGenerator { + /// Whether to generate access specifiers + gen_access_specifiers: bool, /// The module index for which we generate code. #[allow(unused)] module_idx: FF::ModuleHandleIndex, @@ -95,6 +101,10 @@ impl ModuleGenerator { ctx: &ModuleContext, module_env: &ModuleEnv, ) -> (FF::CompiledModule, SourceMap, Option) { + let options = module_env.env.get_extension::().expect("options"); + let gen_access_specifiers = options.language_version.unwrap_or_default() + >= LanguageVersion::V2_0 + && options.experiment_on(Experiment::GEN_ACCESS_SPECIFIERS); let module = move_binary_format::CompiledModule { version: file_format_common::VERSION_NEXT, self_module_handle_idx: FF::ModuleHandleIndex(0), @@ -115,6 +125,7 @@ impl ModuleGenerator { SourceMap::new(ctx.env.to_ir_loc(&module_env.get_loc()), module_name_opt) }; let mut gen = Self { + gen_access_specifiers, module_idx: FF::ModuleHandleIndex(0), module_to_idx: Default::default(), name_to_idx: Default::default(), @@ -418,11 +429,34 @@ impl ModuleGenerator { loc, fun_env.get_result_type().flatten().into_iter().collect(), ); - let access_specifiers = fun_env.get_access_specifiers().as_ref().map(|v| { - v.iter() - .map(|s| self.access_specifier(ctx, fun_env, s)) - .collect() - }); + let access_specifiers = if self.gen_access_specifiers { + fun_env.get_access_specifiers().as_ref().map(|v| { + v.iter() + .map(|s| self.access_specifier(ctx, fun_env, s)) + .collect() + }) + } else { + // Report an error if we cannot drop the access specifiers. + // TODO(#12623): remove this once the bug is fixed + if fun_env + .get_access_specifiers() + .map(|v| { + v.iter().any(|s| { + s.kind != AccessKind::Acquires + || s.negated + || !matches!(s.resource.1, ResourceSpecifier::Resource(_)) + || !matches!(s.address.1, AddressSpecifier::Any) + }) + }) + .unwrap_or_default() + { + ctx.internal_error( + loc, + "cannot strip extended access specifiers to mitigate bug #12623", + ) + } + None + }; let handle = FF::FunctionHandle { module, name, diff --git a/third_party/move/move-compiler-v2/src/lib.rs b/third_party/move/move-compiler-v2/src/lib.rs index 66414573049eb..08d687490a80d 100644 --- a/third_party/move/move-compiler-v2/src/lib.rs +++ b/third_party/move/move-compiler-v2/src/lib.rs @@ -227,7 +227,7 @@ pub fn run_checker(options: Options) -> anyhow::Result { } else { &options.known_attributes }, - !options.experiment_on(Experiment::ACQUIRES_CHECK), + options.language_version.unwrap_or_default(), )?; // Store address aliases let map = addrs diff --git a/third_party/move/move-compiler-v2/src/options.rs b/third_party/move/move-compiler-v2/src/options.rs index 847e4ce5063d0..6ea10c5f4f57d 100644 --- a/third_party/move/move-compiler-v2/src/options.rs +++ b/third_party/move/move-compiler-v2/src/options.rs @@ -8,6 +8,7 @@ use codespan_reporting::diagnostic::Severity; use itertools::Itertools; use move_command_line_common::env::read_env_var; use move_compiler::command_line as cli; +use move_model::metadata::LanguageVersion; use once_cell::sync::Lazy; use std::{ cell::RefCell, @@ -33,6 +34,9 @@ pub struct Options { /// Output directory. #[clap(short, long, default_value = "")] pub output_dir: String, + /// The language version to use. + #[clap(long, value_parser = clap::value_parser!(LanguageVersion))] + pub language_version: Option, /// Do not complain about unknown attributes in Move code. #[clap(long, default_value = "false")] pub skip_attribute_checks: bool, @@ -91,6 +95,14 @@ impl Options { self } + /// Sets the language version to use. + pub fn set_language_version(self, version: LanguageVersion) -> Self { + Self { + language_version: Some(version), + ..self + } + } + /// Returns true if an experiment is on. pub fn experiment_on(&self, name: &str) -> bool { self.experiment_on_recursive(name, &mut BTreeSet::new()) diff --git a/third_party/move/move-compiler-v2/tests/acquires-checker/access_ok.exp b/third_party/move/move-compiler-v2/tests/acquires-checker/access_ok.exp deleted file mode 100644 index f134bf66e2c69..0000000000000 --- a/third_party/move/move-compiler-v2/tests/acquires-checker/access_ok.exp +++ /dev/null @@ -1,91 +0,0 @@ - -Diagnostics: -error: access specifier not enabled. Only plain `acquires ` is enabled. - ┌─ tests/acquires-checker/access_ok.move:11:20 - │ -11 │ fun f2() reads S { - │ ^^ - -error: access specifier not enabled. Only plain `acquires ` is enabled. - ┌─ tests/acquires-checker/access_ok.move:14:21 - │ -14 │ fun f3() writes S { - │ ^^ - -error: access specifier not enabled. Only plain `acquires ` is enabled. - ┌─ tests/acquires-checker/access_ok.move:17:24 - │ -17 │ fun f4() acquires S(*) { - │ ^^^ - -error: access specifier not enabled. Only plain `acquires ` is enabled. - ┌─ tests/acquires-checker/access_ok.move:20:39 - │ -20 │ fun f_multiple() acquires R reads R writes T, S reads G { - │ ^^ - -error: access specifier not enabled. Only plain `acquires ` is enabled. - ┌─ tests/acquires-checker/access_ok.move:20:48 - │ -20 │ fun f_multiple() acquires R reads R writes T, S reads G { - │ ^ - -error: access specifier not enabled. Only plain `acquires ` is enabled. - ┌─ tests/acquires-checker/access_ok.move:20:51 - │ -20 │ fun f_multiple() acquires R reads R writes T, S reads G { - │ ^^ - -error: access specifier not enabled. Only plain `acquires ` is enabled. - ┌─ tests/acquires-checker/access_ok.move:20:59 - │ -20 │ fun f_multiple() acquires R reads R writes T, S reads G { - │ ^^^^^^^ - -error: access specifier not enabled. Only plain `acquires ` is enabled. - ┌─ tests/acquires-checker/access_ok.move:23:23 - │ -23 │ fun f5() acquires 0x42::*::* { - │ ^^^^^^^^^^^ - -error: access specifier not enabled. Only plain `acquires ` is enabled. - ┌─ tests/acquires-checker/access_ok.move:26:23 - │ -26 │ fun f6() acquires 0x42::m::* { - │ ^^^^^^^^^^^ - -error: access specifier not enabled. Only plain `acquires ` is enabled. - ┌─ tests/acquires-checker/access_ok.move:29:23 - │ -29 │ fun f7() acquires *(*) { - │ ^^^^ - -error: access specifier not enabled. Only plain `acquires ` is enabled. - ┌─ tests/acquires-checker/access_ok.move:32:23 - │ -32 │ fun f8() acquires *(0x42) { - │ ^^^^^^^ - -error: access specifier not enabled. Only plain `acquires ` is enabled. - ┌─ tests/acquires-checker/access_ok.move:35:33 - │ -35 │ fun f9(a: address) acquires *(a) { - │ ^^^^ - -error: access specifier not enabled. Only plain `acquires ` is enabled. - ┌─ tests/acquires-checker/access_ok.move:38:30 - │ -38 │ fun f10(x: u64) acquires *(make_up_address(x)) { - │ ^^^^^^^^^^^^^^^^^^^^^ - -error: access specifier not enabled. Only plain `acquires ` is enabled. - ┌─ tests/acquires-checker/access_ok.move:45:22 - │ -45 │ fun f11() !reads *(0x42), *(0x43) { - │ ^^^^^^^ - -error: access specifier not enabled. Only plain `acquires ` is enabled. - ┌─ tests/acquires-checker/access_ok.move:45:31 - │ -45 │ fun f11() !reads *(0x42), *(0x43) { - │ ^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/checking-lang-v1/access_ok.exp b/third_party/move/move-compiler-v2/tests/checking-lang-v1/access_ok.exp new file mode 100644 index 0000000000000..87fdfa3004da6 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking-lang-v1/access_ok.exp @@ -0,0 +1,139 @@ + +Diagnostics: +error: not supported before language version `2.0-unstable`: read/write access specifiers. Try `acquires` instead. + ┌─ tests/checking-lang-v1/access_ok.move:11:20 + │ +11 │ fun f2() reads S { + │ ^^ + +error: not supported before language version `2.0-unstable`: read/write access specifiers. Try `acquires` instead. + ┌─ tests/checking-lang-v1/access_ok.move:14:21 + │ +14 │ fun f3() writes S { + │ ^^ + +error: not supported before language version `2.0-unstable`: wildcard address specifiers + ┌─ tests/checking-lang-v1/access_ok.move:17:24 + │ +17 │ fun f4() acquires S(*) { + │ ^^^ + +error: not supported before language version `2.0-unstable`: read/write access specifiers. Try `acquires` instead. + ┌─ tests/checking-lang-v1/access_ok.move:20:39 + │ +20 │ fun f_multiple() acquires R reads R writes T, S reads G { + │ ^^ + +error: not supported before language version `2.0-unstable`: read/write access specifiers. Try `acquires` instead. + ┌─ tests/checking-lang-v1/access_ok.move:20:48 + │ +20 │ fun f_multiple() acquires R reads R writes T, S reads G { + │ ^ + +error: not supported before language version `2.0-unstable`: read/write access specifiers. Try `acquires` instead. + ┌─ tests/checking-lang-v1/access_ok.move:20:51 + │ +20 │ fun f_multiple() acquires R reads R writes T, S reads G { + │ ^^ + +error: not supported before language version `2.0-unstable`: read/write access specifiers. Try `acquires` instead. + ┌─ tests/checking-lang-v1/access_ok.move:20:59 + │ +20 │ fun f_multiple() acquires R reads R writes T, S reads G { + │ ^^^^^^^ + +error: not supported before language version `2.0-unstable`: address and wildcard access specifiers. Only resource type names can be provided. + ┌─ tests/checking-lang-v1/access_ok.move:23:23 + │ +23 │ fun f5() acquires 0x42::*::* { + │ ^^^^^^^^^^^ + +error: not supported before language version `2.0-unstable`: address and wildcard access specifiers. Only resource type names can be provided. + ┌─ tests/checking-lang-v1/access_ok.move:26:23 + │ +26 │ fun f6() acquires 0x42::m::* { + │ ^^^^^^^^^^^ + +error: not supported before language version `2.0-unstable`: wildcard address specifiers + ┌─ tests/checking-lang-v1/access_ok.move:29:24 + │ +29 │ fun f7() acquires *(*) { + │ ^^^ + +error: not supported before language version `2.0-unstable`: address and wildcard access specifiers. Only resource type names can be provided. + ┌─ tests/checking-lang-v1/access_ok.move:29:23 + │ +29 │ fun f7() acquires *(*) { + │ ^^^^ + +error: not supported before language version `2.0-unstable`: literal address specifiers + ┌─ tests/checking-lang-v1/access_ok.move:32:24 + │ +32 │ fun f8() acquires *(0x42) { + │ ^^^^^^ + +error: not supported before language version `2.0-unstable`: address and wildcard access specifiers. Only resource type names can be provided. + ┌─ tests/checking-lang-v1/access_ok.move:32:23 + │ +32 │ fun f8() acquires *(0x42) { + │ ^^^^^^^ + +error: not supported before language version `2.0-unstable`: named address specifiers + ┌─ tests/checking-lang-v1/access_ok.move:35:34 + │ +35 │ fun f9(a: address) acquires *(a) { + │ ^^^ + +error: not supported before language version `2.0-unstable`: address and wildcard access specifiers. Only resource type names can be provided. + ┌─ tests/checking-lang-v1/access_ok.move:35:33 + │ +35 │ fun f9(a: address) acquires *(a) { + │ ^^^^ + +error: not supported before language version `2.0-unstable`: derived address specifiers + ┌─ tests/checking-lang-v1/access_ok.move:38:31 + │ +38 │ fun f10(x: u64) acquires *(make_up_address(x)) { + │ ^^^^^^^^^^^^^^^^^^^^ + +error: not supported before language version `2.0-unstable`: address and wildcard access specifiers. Only resource type names can be provided. + ┌─ tests/checking-lang-v1/access_ok.move:38:30 + │ +38 │ fun f10(x: u64) acquires *(make_up_address(x)) { + │ ^^^^^^^^^^^^^^^^^^^^^ + +error: not supported before language version `2.0-unstable`: literal address specifiers + ┌─ tests/checking-lang-v1/access_ok.move:45:23 + │ +45 │ fun f11() !reads *(0x42), *(0x43) { + │ ^^^^^^ + +error: not supported before language version `2.0-unstable`: address and wildcard access specifiers. Only resource type names can be provided. + ┌─ tests/checking-lang-v1/access_ok.move:45:22 + │ +45 │ fun f11() !reads *(0x42), *(0x43) { + │ ^^^^^^^ + +error: not supported before language version `2.0-unstable`: read/write access specifiers. Try `acquires` instead. + ┌─ tests/checking-lang-v1/access_ok.move:45:22 + │ +45 │ fun f11() !reads *(0x42), *(0x43) { + │ ^^^^^^^ + +error: not supported before language version `2.0-unstable`: literal address specifiers + ┌─ tests/checking-lang-v1/access_ok.move:45:32 + │ +45 │ fun f11() !reads *(0x42), *(0x43) { + │ ^^^^^^ + +error: not supported before language version `2.0-unstable`: address and wildcard access specifiers. Only resource type names can be provided. + ┌─ tests/checking-lang-v1/access_ok.move:45:31 + │ +45 │ fun f11() !reads *(0x42), *(0x43) { + │ ^^^^^^^ + +error: not supported before language version `2.0-unstable`: read/write access specifiers. Try `acquires` instead. + ┌─ tests/checking-lang-v1/access_ok.move:45:31 + │ +45 │ fun f11() !reads *(0x42), *(0x43) { + │ ^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/acquires-checker/access_ok.move b/third_party/move/move-compiler-v2/tests/checking-lang-v1/access_ok.move similarity index 100% rename from third_party/move/move-compiler-v2/tests/acquires-checker/access_ok.move rename to third_party/move/move-compiler-v2/tests/checking-lang-v1/access_ok.move diff --git a/third_party/move/move-compiler-v2/tests/acquires-checker/conditional_global_operations.exp b/third_party/move/move-compiler-v2/tests/checking-lang-v1/conditional_global_operations.exp similarity index 73% rename from third_party/move/move-compiler-v2/tests/acquires-checker/conditional_global_operations.exp rename to third_party/move/move-compiler-v2/tests/checking-lang-v1/conditional_global_operations.exp index a4a3605e4f005..52ead3995a3e5 100644 --- a/third_party/move/move-compiler-v2/tests/acquires-checker/conditional_global_operations.exp +++ b/third_party/move/move-compiler-v2/tests/checking-lang-v1/conditional_global_operations.exp @@ -1,25 +1,25 @@ Diagnostics: -error: access specifier not enabled. Only plain `acquires ` is enabled. - ┌─ tests/acquires-checker/conditional_global_operations.move:14:49 +error: not supported before language version `2.0-unstable`: access specifier type instantiation. Try removing the type instantiation. + ┌─ tests/checking-lang-v1/conditional_global_operations.move:14:49 │ 14 │ fun ex(s: &signer, a1: address) acquires Box, Box, Pair { │ ^^^^^^ -error: access specifier not enabled. Only plain `acquires ` is enabled. - ┌─ tests/acquires-checker/conditional_global_operations.move:14:57 +error: not supported before language version `2.0-unstable`: access specifier type instantiation. Try removing the type instantiation. + ┌─ tests/checking-lang-v1/conditional_global_operations.move:14:57 │ 14 │ fun ex(s: &signer, a1: address) acquires Box, Box, Pair { │ ^^^^^^ -error: access specifier not enabled. Only plain `acquires ` is enabled. - ┌─ tests/acquires-checker/conditional_global_operations.move:14:65 +error: not supported before language version `2.0-unstable`: access specifier type instantiation. Try removing the type instantiation. + ┌─ tests/checking-lang-v1/conditional_global_operations.move:14:65 │ 14 │ fun ex(s: &signer, a1: address) acquires Box, Box, Pair { │ ^^^^^^^^^^^ error: type `R` is missing required ability `store` (type was inferred) - ┌─ tests/acquires-checker/conditional_global_operations.move:15:9 + ┌─ tests/checking-lang-v1/conditional_global_operations.move:15:9 │ 15 │ move_to(s, Box { f: R {} }); │ ^^^^^^^ @@ -28,7 +28,7 @@ error: type `R` is missing required ability `store` (type was inferred) = required by instantiating type parameter `T:key` of function `move_to` error: type `T` is missing required ability `store` - ┌─ tests/acquires-checker/conditional_global_operations.move:16:23 + ┌─ tests/checking-lang-v1/conditional_global_operations.move:16:23 │ 16 │ borrow_global>(a1); │ ^^^^^^ @@ -37,7 +37,7 @@ error: type `T` is missing required ability `store` = required by instantiating type parameter `T:key` of function `borrow_global` error: type `T` is missing required ability `store` - ┌─ tests/acquires-checker/conditional_global_operations.move:17:27 + ┌─ tests/checking-lang-v1/conditional_global_operations.move:17:27 │ 17 │ borrow_global_mut>>(a1); │ ^^^^^^^^^^^ @@ -47,7 +47,7 @@ error: type `T` is missing required ability `store` = required by instantiating type parameter `T:key` of function `borrow_global_mut` error: type `R` is missing required ability `store` - ┌─ tests/acquires-checker/conditional_global_operations.move:18:43 + ┌─ tests/checking-lang-v1/conditional_global_operations.move:18:43 │ 18 │ Pair { f1: _, f2: _ } = move_from>(a1); │ ^^^^^^^^^^ @@ -56,7 +56,7 @@ error: type `R` is missing required ability `store` = required by instantiating type parameter `T:key` of function `move_from` error: type `T` is missing required ability `store` - ┌─ tests/acquires-checker/conditional_global_operations.move:19:16 + ┌─ tests/checking-lang-v1/conditional_global_operations.move:19:16 │ 19 │ exists, S>>(a1); │ ^^^^^^^^^^^^^^^ @@ -66,7 +66,7 @@ error: type `T` is missing required ability `store` = required by instantiating type parameter `T:key` of function `exists` error: type `K` is missing required ability `store` - ┌─ tests/acquires-checker/conditional_global_operations.move:21:23 + ┌─ tests/checking-lang-v1/conditional_global_operations.move:21:23 │ 21 │ borrow_global>(a1); │ ^^^^^^ @@ -75,7 +75,7 @@ error: type `K` is missing required ability `store` = required by instantiating type parameter `T:key` of function `borrow_global` error: type `K` is missing required ability `store` - ┌─ tests/acquires-checker/conditional_global_operations.move:22:27 + ┌─ tests/checking-lang-v1/conditional_global_operations.move:22:27 │ 22 │ borrow_global_mut>(a1); │ ^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/acquires-checker/conditional_global_operations.move b/third_party/move/move-compiler-v2/tests/checking-lang-v1/conditional_global_operations.move similarity index 100% rename from third_party/move/move-compiler-v2/tests/acquires-checker/conditional_global_operations.move rename to third_party/move/move-compiler-v2/tests/checking-lang-v1/conditional_global_operations.move diff --git a/third_party/move/move-compiler-v2/tests/acquires-checker/v1-tests/invalid_type_acquire.exp b/third_party/move/move-compiler-v2/tests/checking-lang-v1/invalid_type_acquire.exp similarity index 52% rename from third_party/move/move-compiler-v2/tests/acquires-checker/v1-tests/invalid_type_acquire.exp rename to third_party/move/move-compiler-v2/tests/checking-lang-v1/invalid_type_acquire.exp index 52b025f904402..b3ed2abde218f 100644 --- a/third_party/move/move-compiler-v2/tests/acquires-checker/v1-tests/invalid_type_acquire.exp +++ b/third_party/move/move-compiler-v2/tests/checking-lang-v1/invalid_type_acquire.exp @@ -1,31 +1,31 @@ Diagnostics: -error: access specifier not enabled. Only plain `acquires ` is enabled. - ┌─ tests/acquires-checker/v1-tests/invalid_type_acquire.move:18:9 +error: invalid access specifier + ┌─ tests/checking-lang-v1/invalid_type_acquire.move:18:9 │ 18 │ T, │ ^ -error: invalid access specifier - ┌─ tests/acquires-checker/v1-tests/invalid_type_acquire.move:18:9 +error: not supported before language version `2.0-unstable`: address and wildcard access specifiers. Only resource type names can be provided. + ┌─ tests/checking-lang-v1/invalid_type_acquire.move:18:9 │ 18 │ T, │ ^ -error: access specifier not enabled. Only plain `acquires ` is enabled. - ┌─ tests/acquires-checker/v1-tests/invalid_type_acquire.move:19:9 +error: invalid access specifier + ┌─ tests/checking-lang-v1/invalid_type_acquire.move:19:9 │ 19 │ u64, │ ^^^ -error: invalid access specifier - ┌─ tests/acquires-checker/v1-tests/invalid_type_acquire.move:19:9 +error: not supported before language version `2.0-unstable`: address and wildcard access specifiers. Only resource type names can be provided. + ┌─ tests/checking-lang-v1/invalid_type_acquire.move:19:9 │ 19 │ u64, │ ^^^ error: type `u64` is missing required ability `key` - ┌─ tests/acquires-checker/v1-tests/invalid_type_acquire.move:32:36 + ┌─ tests/checking-lang-v1/invalid_type_acquire.move:32:36 │ 32 │ destroy(account, move_from(a)); │ ^^^ @@ -33,7 +33,7 @@ error: type `u64` is missing required ability `key` = required by instantiating type parameter `T:key` of function `move_from` error: type `S` is missing required ability `key` - ┌─ tests/acquires-checker/v1-tests/invalid_type_acquire.move:34:36 + ┌─ tests/checking-lang-v1/invalid_type_acquire.move:34:36 │ 34 │ destroy(account, move_from(a)); │ ^ diff --git a/third_party/move/move-compiler-v2/tests/acquires-checker/v1-tests/invalid_type_acquire.move b/third_party/move/move-compiler-v2/tests/checking-lang-v1/invalid_type_acquire.move similarity index 100% rename from third_party/move/move-compiler-v2/tests/acquires-checker/v1-tests/invalid_type_acquire.move rename to third_party/move/move-compiler-v2/tests/checking-lang-v1/invalid_type_acquire.move diff --git a/third_party/move/move-compiler-v2/tests/checking-lang-v1/receiver_calls.exp b/third_party/move/move-compiler-v2/tests/checking-lang-v1/receiver_calls.exp new file mode 100644 index 0000000000000..e2834e3e0217f --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking-lang-v1/receiver_calls.exp @@ -0,0 +1,25 @@ + +Diagnostics: +error: not supported before language version `2.0-unstable`: receiver style function calls + ┌─ tests/checking-lang-v1/receiver_calls.move:24:9 + │ +24 │ s.receiver(1); + │ ^^^^^^^^^^^^^ + +error: not supported before language version `2.0-unstable`: receiver style function calls + ┌─ tests/checking-lang-v1/receiver_calls.move:25:9 + │ +25 │ s.receiver_ref(1); + │ ^^^^^^^^^^^^^^^^^ + +error: not supported before language version `2.0-unstable`: receiver style function calls + ┌─ tests/checking-lang-v1/receiver_calls.move:26:9 + │ +26 │ s.receiver_ref_mut(1); + │ ^^^^^^^^^^^^^^^^^^^^^ + +error: not supported before language version `2.0-unstable`: receiver style function calls + ┌─ tests/checking-lang-v1/receiver_calls.move:27:9 + │ +27 │ s.inline_receiver_ref_mut(1) + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/checking-lang-v1/receiver_calls.move b/third_party/move/move-compiler-v2/tests/checking-lang-v1/receiver_calls.move new file mode 100644 index 0000000000000..cd8557e12de36 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking-lang-v1/receiver_calls.move @@ -0,0 +1,29 @@ +module 0x42::m { + + struct S { x: u64 } + + // Call styles + + fun receiver(self: S, y: u64): u64 { + self.x + y + } + + fun receiver_ref(self: &S, y: u64): u64 { + self.x + y + } + + fun receiver_ref_mut(self: &mut S, y: u64): u64 { + self.x + y + } + + inline fun inline_receiver_ref_mut(self: &mut S, y: u64): u64 { + self.x + y + } + + fun test_call_styles(s: S): u64 { + s.receiver(1); + s.receiver_ref(1); + s.receiver_ref_mut(1); + s.inline_receiver_ref_mut(1) + } +} diff --git a/third_party/move/move-compiler-v2/tests/testsuite.rs b/third_party/move/move-compiler-v2/tests/testsuite.rs index db5726e9dcc59..55d84c3fdf798 100644 --- a/third_party/move/move-compiler-v2/tests/testsuite.rs +++ b/third_party/move/move-compiler-v2/tests/testsuite.rs @@ -10,7 +10,7 @@ use move_compiler_v2::{ annotate_units, disassemble_compiled_units, env_pipeline::rewrite_target::RewritingScope, logging, pipeline, run_bytecode_verifier, run_file_format_gen, Experiment, Options, }; -use move_model::model::GlobalEnv; +use move_model::{metadata::LanguageVersion, model::GlobalEnv}; use move_prover_test_utils::{baseline_test, extract_test_directives}; use move_stackless_bytecode::function_target_pipeline::FunctionTargetPipeline; use once_cell::unsync::Lazy; @@ -103,7 +103,8 @@ const TEST_CONFIGS: Lazy> = Lazy::new(|| { // Spec rewriter is always on, so we test it, even though it's not part of regular compiler. .set_experiment(Experiment::SPEC_REWRITE, true) // Turn optimization on by default. Some configs below may turn it off. - .set_experiment(Experiment::OPTIMIZE, true); + .set_experiment(Experiment::OPTIMIZE, true) + .set_language_version(LanguageVersion::V2_0); opts.testing = true; let configs = vec![ // --- Tests for checking and ast processing @@ -129,6 +130,20 @@ const TEST_CONFIGS: Lazy> = Lazy::new(|| { dump_bytecode: DumpLevel::None, dump_bytecode_filter: None, }, + // Tests for checking v2 language features only supported if v2 + // language is selected + TestConfig { + name: "checking-lang-v1", + runner: |p| run_test(p, get_config_by_name("checking-lang-v1")), + include: vec!["/checking-lang-v1/"], + exclude: vec![], + exp_suffix: None, + options: opts.clone().set_language_version(LanguageVersion::V1), + stop_after: StopAfter::AstPipeline, + dump_ast: DumpLevel::EndStage, + dump_bytecode: DumpLevel::None, + dump_bytecode_filter: None, + }, // Tests for lambda lifting TestConfig { name: "lambda-lifting", diff --git a/third_party/move/move-compiler-v2/transactional-tests/Cargo.toml b/third_party/move/move-compiler-v2/transactional-tests/Cargo.toml index 35e10a021f479..724f6727c55cd 100644 --- a/third_party/move/move-compiler-v2/transactional-tests/Cargo.toml +++ b/third_party/move/move-compiler-v2/transactional-tests/Cargo.toml @@ -14,6 +14,7 @@ once_cell = "1.7.2" datatest-stable = "0.1.1" itertools = "0.10.3" move-compiler-v2 = { path = ".." } +move-model = { path = "../../move-model" } move-transactional-test-runner = { path = "../../testing-infra/transactional-test-runner" } walkdir = "2.3.3" diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/tests.rs b/third_party/move/move-compiler-v2/transactional-tests/tests/tests.rs index 29a4bb4df3602..6dedc4c08267c 100644 --- a/third_party/move/move-compiler-v2/transactional-tests/tests/tests.rs +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/tests.rs @@ -8,6 +8,7 @@ use datatest_stable::Requirements; use itertools::Itertools; use move_command_line_common::env::read_bool_env_var; use move_compiler_v2::{logging, Experiment}; +use move_model::metadata::LanguageVersion; use move_transactional_test_runner::{vm_test_harness, vm_test_harness::TestRunConfig}; use once_cell::sync::Lazy; use std::{path::Path, string::ToString}; @@ -26,6 +27,7 @@ struct TestConfig { name: &'static str, runner: fn(&Path) -> datatest_stable::Result<()>, experiments: &'static [(&'static str, bool)], + language_version: LanguageVersion, } const TEST_CONFIGS: &[TestConfig] = &[ @@ -36,6 +38,7 @@ const TEST_CONFIGS: &[TestConfig] = &[ (Experiment::OPTIMIZE, true), (Experiment::ACQUIRES_CHECK, false), ], + language_version: LanguageVersion::V2_0, }, TestConfig { name: "no-optimize", @@ -44,6 +47,7 @@ const TEST_CONFIGS: &[TestConfig] = &[ (Experiment::OPTIMIZE, false), (Experiment::ACQUIRES_CHECK, false), ], + language_version: LanguageVersion::V2_0, }, TestConfig { name: "optimize-no-simplify", @@ -53,6 +57,7 @@ const TEST_CONFIGS: &[TestConfig] = &[ (Experiment::AST_SIMPLIFY, false), (Experiment::ACQUIRES_CHECK, false), ], + language_version: LanguageVersion::V2_0, }, ]; @@ -82,15 +87,26 @@ fn run(path: &Path, config: TestConfig) -> datatest_stable::Result<()> { } else { None }; - let v2_experiments = config + let mut v2_experiments = config .experiments .iter() .map(|(s, v)| (s.to_string(), *v)) .collect_vec(); + if path.to_string_lossy().contains("/access_control/") { + // Enable access control file format generation for those tests + v2_experiments.push((Experiment::GEN_ACCESS_SPECIFIERS.to_string(), true)) + } + let language_version = config.language_version; let vm_test_config = if p.contains(SKIP_V1_COMPARISON_PATH) || move_test_debug() { - TestRunConfig::CompilerV2 { v2_experiments } + TestRunConfig::CompilerV2 { + language_version, + v2_experiments, + } } else { - TestRunConfig::ComparisonV1V2 { v2_experiments } + TestRunConfig::ComparisonV1V2 { + language_version, + v2_experiments, + } }; vm_test_harness::run_test_with_config_and_exp_suffix(vm_test_config, path, &exp_suffix) } diff --git a/third_party/move/move-model/src/builder/exp_builder.rs b/third_party/move/move-model/src/builder/exp_builder.rs index 5009b6bd810ea..4e26c60012699 100644 --- a/third_party/move/move-model/src/builder/exp_builder.rs +++ b/third_party/move/move-model/src/builder/exp_builder.rs @@ -11,11 +11,11 @@ use crate::{ model_builder::{AnyFunEntry, ConstEntry, EntryVisibility, LocalVarEntry, StructEntry}, module_builder::{ModuleBuilder, SpecBlockContext}, }, + metadata::LanguageVersion, model::{ FieldId, GlobalEnv, Loc, ModuleId, NodeId, Parameter, QualifiedId, QualifiedInstId, SpecFunId, StructId, TypeParameter, TypeParameterKind, }, - options::ModelBuilderOptions, symbol::{Symbol, SymbolPool}, ty::{ AbilityContext, Constraint, ConstraintContext, ErrorMessageContext, PrimitiveType, @@ -167,6 +167,18 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo et } + pub fn check_language_version(&self, loc: &Loc, feature: &str, version_min: LanguageVersion) { + if self.env().language_version() < version_min { + self.env().error( + loc, + &format!( + "not supported before language version `{}`: {}", + version_min, feature + ), + ) + } + } + pub fn set_spec_block_map(&mut self, map: BTreeMap) { self.spec_block_map = map } @@ -1074,23 +1086,10 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo }) } - fn invalid_acquries(&mut self, loc: &Loc) { - self.error( - loc, - "access specifier not enabled. Only plain `acquires ` is enabled.", - ); - } - fn translate_access_specifier( &mut self, specifier: &EA::AccessSpecifier, ) -> Option { - let options = self - .env() - .get_extension::() - .unwrap_or_default(); - let support_access_specifier = options.support_access_specifier; - fn is_wildcard(name: &Name) -> bool { name.value.as_str() == "*" } @@ -1105,13 +1104,20 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo type_args, address, } = &specifier.value; - if !support_access_specifier - && (*kind != file_format::AccessKind::Acquires - || *negated - || type_args.is_some() && !type_args.as_ref().unwrap().is_empty()) - { - self.invalid_acquries(&loc); - return None; + if *kind != file_format::AccessKind::Acquires { + self.check_language_version( + &loc, + "read/write access specifiers. Try `acquires` instead.", + LanguageVersion::V2_0, + ) + } else if *negated { + self.check_language_version(&loc, "access specifier negation", LanguageVersion::V2_0) + } else if type_args.is_some() && !type_args.as_ref().unwrap().is_empty() { + self.check_language_version( + &loc, + "access specifier type instantiation. Try removing the type instantiation.", + LanguageVersion::V2_0, + ) } let resource = match (module_address, module_name, resource_name) { (None, None, None) => { @@ -1187,7 +1193,11 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo (Some(_), Some(module), Some(resource)) if is_wildcard(&module.0) && !is_wildcard(resource) => { - self.error(&loc, "invalid access specifier: a wildcard cannot be followed by a non-wildcard name component"); + self.error( + &loc, + "invalid access specifier: a wildcard \ + cannot be followed by a non-wildcard name component", + ); ResourceSpecifier::Any }, _ => { @@ -1195,11 +1205,14 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo ResourceSpecifier::Any }, }; - if !support_access_specifier && !matches!(resource, ResourceSpecifier::Resource(..)) { - self.invalid_acquries(&loc); - return None; + if !matches!(resource, ResourceSpecifier::Resource(..)) { + self.check_language_version( + &loc, + "address and wildcard access specifiers. Only resource type names can be provided.", + LanguageVersion::V2_0, + ); } - let address = self.translate_address_specifier(address, support_access_specifier)?; + let address = self.translate_address_specifier(address)?; Some(AccessSpecifier { loc: loc.clone(), kind: *kind, @@ -1212,24 +1225,35 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo fn translate_address_specifier( &mut self, specifier: &EA::AddressSpecifier, - support_access_specifier: bool, ) -> Option<(Loc, AddressSpecifier)> { let loc = self.to_loc(&specifier.loc); let res = match &specifier.value { EA::AddressSpecifier_::Empty => (loc, AddressSpecifier::Any), EA::AddressSpecifier_::Any => { - if support_access_specifier { - (loc, AddressSpecifier::Any) - } else { - self.invalid_acquries(&loc); - return None; - } + self.check_language_version( + &loc, + "wildcard address specifiers", + LanguageVersion::V2_0, + ); + (loc, AddressSpecifier::Any) + }, + EA::AddressSpecifier_::Literal(addr) => { + self.check_language_version( + &loc, + "literal address specifiers", + LanguageVersion::V2_0, + ); + ( + loc, + AddressSpecifier::Address(Address::Numerical(addr.into_inner())), + ) }, - EA::AddressSpecifier_::Literal(addr) => ( - loc, - AddressSpecifier::Address(Address::Numerical(addr.into_inner())), - ), EA::AddressSpecifier_::Name(name) => { + self.check_language_version( + &loc, + "named address specifiers", + LanguageVersion::V2_0, + ); // Construct an expansion name exp for regular type check let maccess = sp(name.loc, EA::ModuleAccess_::Name(*name)); self.translate_name( @@ -1245,10 +1269,11 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo ) }, EA::AddressSpecifier_::Call(maccess, type_args, name) => { - if !support_access_specifier { - self.invalid_acquries(&loc); - return None; - } + self.check_language_version( + &loc, + "derived address specifiers", + LanguageVersion::V2_0, + ); // Construct an expansion function call for regular type check let name_exp = sp( name.loc, @@ -3489,6 +3514,7 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo args: Vec, expected_type: &Type, ) -> ExpData { + self.check_language_version(loc, "receiver style function calls", LanguageVersion::V2_0); let generics = generics .as_ref() .map(|tys| self.translate_types_with_loc(tys)); diff --git a/third_party/move/move-model/src/lib.rs b/third_party/move/move-model/src/lib.rs index b03b48a9e3f9c..d9ad6518e72a5 100644 --- a/third_party/move/move-model/src/lib.rs +++ b/third_party/move/move-model/src/lib.rs @@ -7,6 +7,7 @@ use crate::{ ast::ModuleName, builder::{model_builder::ModelBuilder, module_builder::BytecodeModule}, + metadata::LanguageVersion, model::{FunId, GlobalEnv, Loc, ModuleId, StructId}, options::ModelBuilderOptions, }; @@ -53,6 +54,7 @@ pub mod constant_folder; pub mod exp_generator; pub mod exp_rewriter; pub mod intrinsics; +pub mod metadata; pub mod model; pub mod options; pub mod pragmas; @@ -82,7 +84,7 @@ pub fn run_model_builder_in_compiler_mode( deps: Vec, skip_attribute_checks: bool, known_attributes: &BTreeSet, - support_access_specifier: bool, + language_version: LanguageVersion, ) -> anyhow::Result { let to_package_paths = |PackageInfo { sources, @@ -97,7 +99,7 @@ pub fn run_model_builder_in_compiler_mode( deps.into_iter().map(to_package_paths).collect(), ModelBuilderOptions { compile_via_model: true, - support_access_specifier, + language_version, ..ModelBuilderOptions::default() }, Flags::model_compilation().set_skip_attribute_checks(skip_attribute_checks), @@ -142,6 +144,7 @@ pub fn run_model_builder_with_options_and_compilation_flags< known_attributes: &BTreeSet, ) -> anyhow::Result { let mut env = GlobalEnv::new(); + env.set_language_version(options.language_version); let compile_via_model = options.compile_via_model; env.set_extension(options); diff --git a/third_party/move/move-model/src/metadata.rs b/third_party/move/move-model/src/metadata.rs new file mode 100644 index 0000000000000..0aa997e299e77 --- /dev/null +++ b/third_party/move/move-model/src/metadata.rs @@ -0,0 +1,230 @@ +// Copyright (c) Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use anyhow::bail; +use move_command_line_common::env::read_bool_env_var; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; +use std::{ + fmt, + fmt::{Display, Formatter}, + str::FromStr, +}; + +const UNSTABLE_MARKER: &str = "-unstable"; + +// ================================================================================' +// Metadata for compilation result (WORK IN PROGRESS) + +/// Metadata about a compilation result. To maintain serialization +/// stability, this uses a free-form string to represent compiler version +/// and language version, which is interpreted by the `CompilerVersion` +/// and `LanguageVersion` types. This allows to always successfully +/// deserialize the metadata (even older code with newer data), and leave it +/// up to the program how to deal with decoding errors. +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +pub struct CompilationMetadata { + /// A flag indicating whether, at time of creation, the compilation + /// result was considered as unstable. Unstable code may have restrictions + /// for deployment on production networks. This flag is true if either the + /// compiler or language versions are unstable. + pub unstable: bool, + /// The version of the compiler, as a string. See + /// `CompilationVersion::from_str` for supported version strings. + pub compiler_version: String, + /// The version of the language, as a string. See + /// `LanguageVersion::from_str` for supported version strings. + pub language_version: String, +} + +impl CompilationMetadata { + pub fn new(compiler_version: CompilerVersion, language_version: LanguageVersion) -> Self { + Self { + compiler_version: compiler_version.to_string(), + language_version: language_version.to_string(), + unstable: compiler_version.unstable() || language_version.unstable(), + } + } + + pub fn compiler_version(&self) -> anyhow::Result { + CompilerVersion::from_str(&self.compiler_version) + } + + pub fn language_version(&self) -> anyhow::Result { + LanguageVersion::from_str(&self.language_version) + } + + /// Returns true of the compilation was created as unstable. + pub fn created_as_unstable(&self) -> bool { + self.unstable + } +} + +// ================================================================================' +// Compiler Version + +/// Represents a compiler version. +/// +/// The versioning scheme is `major.minor`, where for `major = 1` we do not +/// distinguish a minor version. A major version change represents +/// a different/largely refactored compiler. This we have versions `1, 2.0, 2.1, 2.2, .., `. +#[derive(Clone, Copy, Debug, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] +pub enum CompilerVersion { + /// The legacy v1 Move compiler + V1, + /// The v2 compiler, starting with 2.0-unstable. Each new released version of the compiler + /// should get an enum entry here. + V2_0, +} + +impl Default for CompilerVersion { + /// We allow the default to be set via an environment variable. + fn default() -> Self { + static MOVE_COMPILER_V2: Lazy = Lazy::new(|| read_bool_env_var("MOVE_COMPILER_V2")); + if *MOVE_COMPILER_V2 { + Self::V2_0 + } else { + Self::V1 + } + } +} + +impl FromStr for CompilerVersion { + type Err = anyhow::Error; + + /// Parses a compiler version. If the caller only provides a major + /// version number, this chooses the latest stable minor version (if any). + fn from_str(s: &str) -> Result { + // Strip unstable marker as it is not relevant for parsing. + let s1 = s.replace(UNSTABLE_MARKER, ""); + match s1.as_str() { + // For legacy reasons, also support v1 and v2 + "1" | "v1" => Ok(Self::V1), + "2" | "v2" | "2.0" => Ok(Self::V2_0), + _ => bail!( + "unrecognized compiler version `{}` (supported versions: `1`, `2`, `2.0`)", + s + ), + } + } +} + +impl Display for CompilerVersion { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!( + f, + "{}{}", + match self { + CompilerVersion::V1 => "1", + CompilerVersion::V2_0 => "2.0", + }, + if self.unstable() { UNSTABLE_MARKER } else { "" } + ) + } +} + +impl CompilerVersion { + /// Return true if this is a stable compiler version. A non-stable version + /// should not be allowed on production networks. + pub fn unstable(self) -> bool { + match self { + CompilerVersion::V1 => false, + CompilerVersion::V2_0 => true, + } + } + + /// Check whether the compiler version supports the given language version, + /// generates an error if not. + pub fn check_language_support(self, version: LanguageVersion) -> anyhow::Result<()> { + match self { + CompilerVersion::V1 => { + if version != LanguageVersion::V1 { + bail!("compiler v1 does only support Move language version 1") + } else { + Ok(()) + } + }, + CompilerVersion::V2_0 => Ok(()), + } + } +} + +// ================================================================================' +// Language Version + +/// Represents a language version. +/// +/// The versioning scheme is `major.minor`, where for `major = 1` we do not +/// distinguish a minor version. This we have versions `1, 2.0, 2.1, .., 3.0, 3.1, ..`. +/// Typically, a major version change is given with an addition of larger new language +/// features. There are no breaking changes expected with major version changes, +/// however, there maybe some isolated exceptions. +#[derive(Clone, Copy, Debug, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] +pub enum LanguageVersion { + /// The version of Move at around the genesis of the Aptos network end + /// of '22. This is the original Diem Move plus the extension of inline + /// functions with lambda parameters, as well as a simple form of `for` + /// loops. + V1, + /// The upcoming (currently unstable) 2.0 version of Move. The following + /// experimental language features are supported so far: + /// + /// - Access control specifiers as described in AIP-56. + /// - Receiver style (method) function calls with auto-referencing + V2_0, +} + +impl Default for LanguageVersion { + fn default() -> Self { + static MOVE_LANGUAGE_V2: Lazy = Lazy::new(|| read_bool_env_var("MOVE_LANGUAGE_V2")); + if *MOVE_LANGUAGE_V2 { + Self::V2_0 + } else { + Self::V1 + } + } +} + +impl FromStr for LanguageVersion { + type Err = anyhow::Error; + + /// Parses a language version. If the caller only provides a major + /// version number, this chooses the latest stable minor version (if any). + fn from_str(s: &str) -> Result { + // Strip unstable marker as it is not relevant for parsing. + let s1 = s.replace(UNSTABLE_MARKER, ""); + match s1.as_str() { + "1" => Ok(Self::V1), + "2" | "2.0" => Ok(Self::V2_0), + _ => bail!( + "unrecognized language version `{}` (supported versions: `1`, `2`, `2.0`)", + s + ), + } + } +} + +impl LanguageVersion { + /// Whether the language version is unstable. An unstable version + /// should not be allowed on production networks. + pub fn unstable(self) -> bool { + match self { + LanguageVersion::V1 => false, + LanguageVersion::V2_0 => true, + } + } +} + +impl Display for LanguageVersion { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}{}", + match self { + LanguageVersion::V1 => "1", + LanguageVersion::V2_0 => "2.0", + }, + if self.unstable() { UNSTABLE_MARKER } else { "" } + ) + } +} diff --git a/third_party/move/move-model/src/model.rs b/third_party/move/move-model/src/model.rs index 75cedf16d4c51..147f908a5c779 100644 --- a/third_party/move/move-model/src/model.rs +++ b/third_party/move/move-model/src/model.rs @@ -24,6 +24,7 @@ use crate::{ code_writer::CodeWriter, emit, emitln, intrinsics::IntrinsicsAnnotation, + metadata::LanguageVersion, pragmas::{ DELEGATE_INVARIANTS_TO_CALLER_PRAGMA, DISABLE_INVARIANTS_IN_BODY_PRAGMA, FRIEND_PRAGMA, INTRINSIC_PRAGMA, OPAQUE_PRAGMA, VERIFY_PRAGMA, @@ -504,6 +505,8 @@ impl VerificationScope { /// Global environment for a set of modules. #[derive(Debug)] pub struct GlobalEnv { + /// The language version for which this model is build. + pub(crate) language_version: LanguageVersion, /// A Files database for the codespan crate which supports diagnostics. pub(crate) source_files: Files, /// A map of FileId in the Files database to information about documentation comments in a file. @@ -602,6 +605,7 @@ impl GlobalEnv { let unknown_move_ir_loc = MoveIrLoc::new(FileHash::new(""), 0, 0); let internal_loc = fake_loc(""); GlobalEnv { + language_version: LanguageVersion::default(), source_files, doc_comments: Default::default(), unknown_loc, @@ -637,11 +641,21 @@ impl GlobalEnv { self.generated_by_v2 = yes } - /// Returns if this is generated by v2. + /// Returns true if this is generated by v2. pub fn generated_by_v2(&self) -> bool { self.generated_by_v2 } + /// Sets the language version. + pub fn set_language_version(&mut self, version: LanguageVersion) { + self.language_version = version + } + + /// Returns the language version + pub fn language_version(&self) -> LanguageVersion { + self.language_version + } + /// Creates a display container for the given value. There must be an implementation /// of fmt::Display for an instance to work in formatting. pub fn display<'a, T>(&'a self, val: &'a T) -> EnvDisplay<'a, T> { diff --git a/third_party/move/move-model/src/options.rs b/third_party/move/move-model/src/options.rs index 9d8ad6c5f7b99..145a90b9c6532 100644 --- a/third_party/move/move-model/src/options.rs +++ b/third_party/move/move-model/src/options.rs @@ -2,15 +2,19 @@ // Copyright (c) The Move Contributors // SPDX-License-Identifier: Apache-2.0 +use crate::metadata::LanguageVersion; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(default, deny_unknown_fields)] pub struct ModelBuilderOptions { - /// Whether compilation of the Move code into bytecode should be handled by the new compiler - /// part of the model. + /// Whether compilation of the Move code into bytecode should be handled via + /// the model builder. pub compile_via_model: bool, + /// The language version to use. + pub language_version: LanguageVersion, + /// Ignore the "opaque" pragma on internal function (i.e., functions with no unknown callers) /// specs when possible. The opaque can be ignored as long as the function spec has no property /// marked as `[concrete]` or `[abstract]`. @@ -19,7 +23,4 @@ pub struct ModelBuilderOptions { /// Ignore the "opaque" pragma on all function specs when possible. The opaque can be ignored /// as long as the function spec has no property marked as `[concrete]` or `[abstract]`. pub ignore_pragma_opaque_when_possible: bool, - - /// Whether to support general access specifiers - pub support_access_specifier: bool, } diff --git a/third_party/move/move-prover/src/cli.rs b/third_party/move/move-prover/src/cli.rs index 70618af31630b..e1accbf68063c 100644 --- a/third_party/move/move-prover/src/cli.rs +++ b/third_party/move/move-prover/src/cli.rs @@ -14,7 +14,9 @@ use move_abigen::AbigenOptions; use move_compiler::{command_line::SKIP_ATTRIBUTE_CHECKS, shared::NumericalAddress}; use move_docgen::DocgenOptions; use move_errmapgen::ErrmapOptions; -use move_model::{model::VerificationScope, options::ModelBuilderOptions}; +use move_model::{ + metadata::LanguageVersion, model::VerificationScope, options::ModelBuilderOptions, +}; use move_prover_boogie_backend::options::{BoogieOptions, CustomNativeOptions, VectorTheory}; use move_prover_bytecode_pipeline::options::{AutoTraceLevel, ProverOptions}; use once_cell::sync::Lazy; @@ -67,7 +69,8 @@ pub struct Options { pub skip_attribute_checks: bool, /// Whether to use compiler v2 to compile Move code pub compiler_v2: bool, - + /// The language version to use + pub language_version: Option, /// BEGIN OF STRUCTURED OPTIONS. DO NOT ADD VALUE FIELDS AFTER THIS /// Options for the model builder. pub model_builder: ModelBuilderOptions, @@ -106,6 +109,7 @@ impl Default for Options { experimental_pipeline: false, skip_attribute_checks: false, compiler_v2: false, + language_version: None, } } } @@ -173,6 +177,12 @@ impl Options { .action(SetTrue) .help("whether to use Move compiler v2 to compile to bytecode") ) + .arg( + Arg::new("language-version") + .long("language-version") + .value_parser(clap::value_parser!(LanguageVersion)) + .help("the language version to use") + ) .arg( Arg::new("output") .short('o') @@ -798,6 +808,11 @@ impl Options { if matches.get_flag("compiler-v2") { options.compiler_v2 = true; } + if matches.contains_id("language-version") { + options.language_version = matches + .get_one::("language-version") + .cloned(); + } options.backend.derive_options(); diff --git a/third_party/move/move-prover/src/lib.rs b/third_party/move/move-prover/src/lib.rs index 1a39800f49e99..98f8de874c9a1 100644 --- a/third_party/move/move-prover/src/lib.rs +++ b/third_party/move/move-prover/src/lib.rs @@ -76,6 +76,7 @@ pub fn run_move_prover_v2( dependencies: cloned_options.move_deps, named_address_mapping: cloned_options.move_named_address_values, output_dir: cloned_options.output_path, + language_version: cloned_options.language_version, skip_attribute_checks: true, known_attributes: Default::default(), testing: cloned_options.backend.stable_test_output, diff --git a/third_party/move/testing-infra/transactional-test-runner/Cargo.toml b/third_party/move/testing-infra/transactional-test-runner/Cargo.toml index d6bd744693a0d..21461e1c8cbd7 100644 --- a/third_party/move/testing-infra/transactional-test-runner/Cargo.toml +++ b/third_party/move/testing-infra/transactional-test-runner/Cargo.toml @@ -22,6 +22,7 @@ move-core-types = { path = "../../move-core/types" } move-disassembler = { path = "../../tools/move-disassembler" } move-ir-compiler = { path = "../../move-ir-compiler" } move-ir-types = { path = "../../move-ir/types" } +move-model = { path = "../../move-model" } move-resource-viewer = { path = "../../tools/move-resource-viewer" } once_cell = "1.7.2" regex = "1.1.9" diff --git a/third_party/move/testing-infra/transactional-test-runner/src/framework.rs b/third_party/move/testing-infra/transactional-test-runner/src/framework.rs index 787477a7eac7c..b3d043105dc92 100644 --- a/third_party/move/testing-infra/transactional-test-runner/src/framework.rs +++ b/third_party/move/testing-infra/transactional-test-runner/src/framework.rs @@ -42,6 +42,7 @@ use move_core_types::{ }; use move_disassembler::disassembler::{Disassembler, DisassemblerOptions}; use move_ir_types::location::Spanned; +use move_model::metadata::LanguageVersion; use move_symbol_pool::Symbol; use move_vm_runtime::session::SerializedReturnValues; use once_cell::sync::Lazy; @@ -198,13 +199,20 @@ pub trait MoveTestAdapter<'a>: Sized { let state = self.compiled_state(); let (named_addr_opt, module, warnings_opt) = match (syntax, run_config) { // Run the V2 compiler if requested - (SyntaxChoice::Source, TestRunConfig::CompilerV2 { v2_experiments }) => { + ( + SyntaxChoice::Source, + TestRunConfig::CompilerV2 { + language_version, + v2_experiments, + }, + ) => { let ((module, _), warning_opt) = compile_source_unit_v2( state.pre_compiled_deps, state.named_address_mapping.clone(), &state.source_files().cloned().collect::>(), data_path.to_owned(), self.known_attributes(), + language_version, v2_experiments, )?; if let Some(module) = module { @@ -265,13 +273,20 @@ pub trait MoveTestAdapter<'a>: Sized { let state = self.compiled_state(); let (script, warning_opt) = match (syntax, run_config) { // Run the V2 compiler if requested. - (SyntaxChoice::Source, TestRunConfig::CompilerV2 { v2_experiments }) => { + ( + SyntaxChoice::Source, + TestRunConfig::CompilerV2 { + language_version, + v2_experiments, + }, + ) => { let ((_, script), warning_opt) = compile_source_unit_v2( state.pre_compiled_deps, state.named_address_mapping.clone(), &state.source_files().cloned().collect::>(), data_path.to_owned(), self.known_attributes(), + language_version, v2_experiments, )?; if let Some(script) = script { @@ -670,6 +685,7 @@ fn compile_source_unit_v2( deps: &[String], path: String, known_attributes: &BTreeSet, + language_version: LanguageVersion, experiments: Vec<(String, bool)>, ) -> Result<( (Option, Option), @@ -702,6 +718,7 @@ fn compile_source_unit_v2( .map(|(alias, addr)| format!("{}={}", alias, addr)) .collect(), known_attributes: known_attributes.clone(), + language_version: Some(language_version), ..move_compiler_v2::Options::default() }; for (exp, value) in experiments { @@ -840,17 +857,21 @@ where }; // Construct a sequence of compiler runs based on the given config. - let (runs, comparison_mode) = - if let TestRunConfig::ComparisonV1V2 { v2_experiments } = config.clone() { - ( - vec![TestRunConfig::CompilerV1, TestRunConfig::CompilerV2 { - v2_experiments, - }], - true, - ) - } else { - (vec![config.clone()], false) // either V1 or V2 - }; + let (runs, comparison_mode) = if let TestRunConfig::ComparisonV1V2 { + language_version, + v2_experiments, + } = config.clone() + { + ( + vec![TestRunConfig::CompilerV1, TestRunConfig::CompilerV2 { + language_version, + v2_experiments, + }], + true, + ) + } else { + (vec![config.clone()], false) // either V1 or V2 + }; let mut last_output = String::new(); let mut bytecode_print_output = BTreeMap::::new(); for run_config in runs { diff --git a/third_party/move/testing-infra/transactional-test-runner/src/vm_test_harness.rs b/third_party/move/testing-infra/transactional-test-runner/src/vm_test_harness.rs index df8f9c2e96409..3c3b76955ce6e 100644 --- a/third_party/move/testing-infra/transactional-test-runner/src/vm_test_harness.rs +++ b/third_party/move/testing-infra/transactional-test-runner/src/vm_test_harness.rs @@ -31,6 +31,7 @@ use move_core_types::{ resolver::MoveResolver, value::MoveValue, }; +use move_model::metadata::LanguageVersion; use move_resource_viewer::MoveValueAnnotator; use move_stdlib::move_stdlib_named_addresses; use move_symbol_pool::Symbol; @@ -448,8 +449,14 @@ static MOVE_STDLIB_COMPILED: Lazy> = Lazy::new(|| { #[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)] pub enum TestRunConfig { CompilerV1, - CompilerV2 { v2_experiments: Vec<(String, bool)> }, - ComparisonV1V2 { v2_experiments: Vec<(String, bool)> }, + CompilerV2 { + language_version: LanguageVersion, + v2_experiments: Vec<(String, bool)>, + }, + ComparisonV1V2 { + language_version: LanguageVersion, + v2_experiments: Vec<(String, bool)>, + }, } pub fn run_test(path: &Path) -> Result<(), Box> { diff --git a/third_party/move/tools/move-cli/src/base/docgen.rs b/third_party/move/tools/move-cli/src/base/docgen.rs index d8f18cd47112c..93118a2749633 100644 --- a/third_party/move/tools/move-cli/src/base/docgen.rs +++ b/third_party/move/tools/move-cli/src/base/docgen.rs @@ -4,7 +4,7 @@ use super::reroot_path; use clap::*; use move_docgen::DocgenOptions; -use move_package::{BuildConfig, CompilerVersion, ModelConfig}; +use move_package::{BuildConfig, ModelConfig}; use std::{fs, path::PathBuf}; /// Generate javadoc style documentation for Move packages @@ -58,14 +58,13 @@ pub struct Docgen { impl Docgen { /// Calling the Docgen pub fn execute(self, path: Option, config: BuildConfig) -> anyhow::Result<()> { - let compiler_version = config - .compiler_config - .compiler_version - .unwrap_or(CompilerVersion::V1); + let compiler_version = config.compiler_config.compiler_version.unwrap_or_default(); + let language_version = config.compiler_config.language_version.unwrap_or_default(); let model = config.move_model_for_package(&reroot_path(path).unwrap(), ModelConfig { all_files_as_targets: false, target_filter: None, compiler_version, + language_version, })?; let mut options = DocgenOptions::default(); diff --git a/third_party/move/tools/move-cli/src/base/errmap.rs b/third_party/move/tools/move-cli/src/base/errmap.rs index 4a1c4b7dffe3d..e8800b147b501 100644 --- a/third_party/move/tools/move-cli/src/base/errmap.rs +++ b/third_party/move/tools/move-cli/src/base/errmap.rs @@ -3,7 +3,8 @@ use super::reroot_path; use clap::*; -use move_package::{BuildConfig, CompilerVersion, ModelConfig}; +use move_model::metadata::{CompilerVersion, LanguageVersion}; +use move_package::{BuildConfig, ModelConfig}; use std::path::PathBuf; /// Generate error map for the package and its dependencies at `path` for use by the Move @@ -39,6 +40,7 @@ impl Errmap { all_files_as_targets: true, target_filter: None, compiler_version: CompilerVersion::default(), + language_version: LanguageVersion::default(), })?; let mut errmap_gen = move_errmapgen::ErrmapGen::new(&model, &errmap_options); errmap_gen.gen(); diff --git a/third_party/move/tools/move-cli/src/base/prove.rs b/third_party/move/tools/move-cli/src/base/prove.rs index 54732e4cf5185..f11e2cbf47ab9 100644 --- a/third_party/move/tools/move-cli/src/base/prove.rs +++ b/third_party/move/tools/move-cli/src/base/prove.rs @@ -191,10 +191,12 @@ pub fn run_move_prover( } let now = Instant::now(); let compiler_version = config.compiler_config.compiler_version.unwrap_or_default(); + let language_version = config.compiler_config.language_version.unwrap_or_default(); let mut model = config.move_model_for_package(path, ModelConfig { all_files_as_targets: false, target_filter: target_filter.clone(), compiler_version, + language_version, })?; let _temp_dir_holder = if for_test { // Need to ensure a distinct output.bpl file for concurrent execution. In non-test diff --git a/third_party/move/tools/move-package/src/compilation/compiled_package.rs b/third_party/move/tools/move-package/src/compilation/compiled_package.rs index c6682c3c80d1b..d96786fb7b808 100644 --- a/third_party/move/tools/move-package/src/compilation/compiled_package.rs +++ b/third_party/move/tools/move-package/src/compilation/compiled_package.rs @@ -633,13 +633,17 @@ impl CompiledPackage { let mut paths = src_deps; paths.push(sources_package_paths.clone()); + let effective_compiler_version = config.compiler_version.unwrap_or_default(); + let effective_language_version = config.language_version.unwrap_or_default(); + effective_compiler_version.check_language_support(effective_language_version)?; + let (file_map, all_compiled_units) = match config.compiler_version.unwrap_or_default() { CompilerVersion::V1 => { let compiler = Compiler::from_package_paths(paths, bytecode_deps, flags, &known_attributes); compiler_driver_v1(compiler)? }, - CompilerVersion::V2 => { + CompilerVersion::V2_0 => { let to_str_vec = |ps: &[Symbol]| { ps.iter() .map(move |s| s.as_str().to_owned()) @@ -677,6 +681,7 @@ impl CompiledPackage { .collect(), skip_attribute_checks, known_attributes: known_attributes.clone(), + language_version: Some(effective_language_version), ..Default::default() }; compiler_driver_v2(options)? diff --git a/third_party/move/tools/move-package/src/compilation/model_builder.rs b/third_party/move/tools/move-package/src/compilation/model_builder.rs index 924374e4d4b10..5807a063f638c 100644 --- a/third_party/move/tools/move-package/src/compilation/model_builder.rs +++ b/third_party/move/tools/move-package/src/compilation/model_builder.rs @@ -135,8 +135,13 @@ impl ModelBuilder { skip_attribute_checks, known_attributes, ), - CompilerVersion::V2 => { + CompilerVersion::V2_0 => { let mut options = make_options_for_v2_compiler(all_targets, all_deps); + options.language_version = self + .resolution_graph + .build_options + .compiler_config + .language_version; options.known_attributes = known_attributes.clone(); options.skip_attribute_checks = skip_attribute_checks; let mut error_writer = StandardStream::stderr(ColorChoice::Auto); diff --git a/third_party/move/tools/move-package/src/lib.rs b/third_party/move/tools/move-package/src/lib.rs index 5b2b42dbf4e97..89ded94d5a966 100644 --- a/third_party/move/tools/move-package/src/lib.rs +++ b/third_party/move/tools/move-package/src/lib.rs @@ -19,13 +19,14 @@ use crate::{ }; use anyhow::{bail, Result}; use clap::*; -use move_command_line_common::env::read_bool_env_var; use move_compiler::{ command_line::SKIP_ATTRIBUTE_CHECKS, shared::known_attributes::KnownAttribute, }; use move_core_types::account_address::AccountAddress; -use move_model::model; -use once_cell::sync::Lazy; +use move_model::{ + metadata::{CompilerVersion, LanguageVersion}, + model, +}; use serde::{Deserialize, Serialize}; use source_package::layout::SourcePackageLayout; use std::{ @@ -166,25 +167,14 @@ pub struct CompilerConfig { pub skip_attribute_checks: bool, /// Compiler version to use - #[clap(long = "compiler-version", global = true)] + #[clap(long = "compiler-version", global = true, + value_parser = clap::value_parser!(CompilerVersion))] pub compiler_version: Option, -} - -#[derive(ValueEnum, Clone, Copy, Debug, Serialize, Deserialize, Eq, PartialEq, PartialOrd)] -pub enum CompilerVersion { - V1, - V2, -} -impl Default for CompilerVersion { - fn default() -> Self { - static MOVE_COMPILER_V2: Lazy = Lazy::new(|| read_bool_env_var("MOVE_COMPILER_V2")); - if *MOVE_COMPILER_V2 { - Self::V2 - } else { - Self::V1 - } - } + /// Language version to support + #[clap(long = "language-version", global = true, + value_parser = clap::value_parser!(LanguageVersion))] + pub language_version: Option, } #[derive(Debug, Clone, Eq, PartialEq, PartialOrd)] @@ -196,6 +186,8 @@ pub struct ModelConfig { pub target_filter: Option, /// The compiler version used to build the model pub compiler_version: CompilerVersion, + /// The language version used to build the model + pub language_version: LanguageVersion, } impl BuildConfig { diff --git a/third_party/move/tools/move-package/tests/test_runner.rs b/third_party/move/tools/move-package/tests/test_runner.rs index 9cf3796e3e374..486959f756b71 100644 --- a/third_party/move/tools/move-package/tests/test_runner.rs +++ b/third_party/move/tools/move-package/tests/test_runner.rs @@ -7,6 +7,7 @@ use move_command_line_common::testing::{ add_update_baseline_fix, format_diff, read_env_update_baseline, EXP_EXT, EXP_EXT_V2, }; use move_compiler::shared::known_attributes::KnownAttribute; +use move_model::metadata::{CompilerVersion, LanguageVersion}; use move_package::{ compilation::{build_plan::BuildPlan, model_builder::ModelBuilder}, package_hooks, @@ -16,7 +17,7 @@ use move_package::{ manifest_parser as MP, parsed_manifest::{CustomDepInfo, PackageDigest}, }, - BuildConfig, CompilerConfig, CompilerVersion, ModelConfig, + BuildConfig, CompilerConfig, ModelConfig, }; use move_symbol_pool::Symbol; use std::{ @@ -85,6 +86,7 @@ fn run_test_impl( all_files_as_targets: false, target_filter: None, compiler_version, + language_version: LanguageVersion::default(), }) .build_model() { @@ -111,7 +113,7 @@ fn check_or_update( update_baseline: bool, compiler_version: CompilerVersion, ) -> datatest_stable::Result<()> { - let exp_ext = if compiler_version == CompilerVersion::V2 { + let exp_ext = if compiler_version == CompilerVersion::V2_0 { EXP_EXT_V2 } else { EXP_EXT diff --git a/third_party/move/tools/move-package/tests/test_sources/compilation/basic_no_deps/Move.exp b/third_party/move/tools/move-package/tests/test_sources/compilation/basic_no_deps/Move.exp index 816366598aa92..c7db84b07c642 100644 --- a/third_party/move/tools/move-package/tests/test_sources/compilation/basic_no_deps/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/compilation/basic_no_deps/Move.exp @@ -34,6 +34,7 @@ CompiledPackageInfo { compiler_version: Some( V1, ), + language_version: None, }, }, } diff --git a/third_party/move/tools/move-package/tests/test_sources/compilation/basic_no_deps_address_assigned/Move.exp b/third_party/move/tools/move-package/tests/test_sources/compilation/basic_no_deps_address_assigned/Move.exp index abc4820b4b8d0..7719a13c2b504 100644 --- a/third_party/move/tools/move-package/tests/test_sources/compilation/basic_no_deps_address_assigned/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/compilation/basic_no_deps_address_assigned/Move.exp @@ -36,6 +36,7 @@ CompiledPackageInfo { compiler_version: Some( V1, ), + language_version: None, }, }, } diff --git a/third_party/move/tools/move-package/tests/test_sources/compilation/basic_no_deps_address_not_assigned_with_dev_assignment/Move.exp b/third_party/move/tools/move-package/tests/test_sources/compilation/basic_no_deps_address_not_assigned_with_dev_assignment/Move.exp index ae656b4055f30..de543cb5e5995 100644 --- a/third_party/move/tools/move-package/tests/test_sources/compilation/basic_no_deps_address_not_assigned_with_dev_assignment/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/compilation/basic_no_deps_address_not_assigned_with_dev_assignment/Move.exp @@ -36,6 +36,7 @@ CompiledPackageInfo { compiler_version: Some( V1, ), + language_version: None, }, }, } diff --git a/third_party/move/tools/move-package/tests/test_sources/compilation/basic_no_deps_test_mode/Move.exp b/third_party/move/tools/move-package/tests/test_sources/compilation/basic_no_deps_test_mode/Move.exp index 9757a9749e7b6..ead9bb2d6164d 100644 --- a/third_party/move/tools/move-package/tests/test_sources/compilation/basic_no_deps_test_mode/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/compilation/basic_no_deps_test_mode/Move.exp @@ -36,6 +36,7 @@ CompiledPackageInfo { compiler_version: Some( V1, ), + language_version: None, }, }, } diff --git a/third_party/move/tools/move-package/tests/test_sources/compilation/diamond_problem_backflow_resolution/Move.exp b/third_party/move/tools/move-package/tests/test_sources/compilation/diamond_problem_backflow_resolution/Move.exp index 5194ca1a281b1..14caf20ea4a78 100644 --- a/third_party/move/tools/move-package/tests/test_sources/compilation/diamond_problem_backflow_resolution/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/compilation/diamond_problem_backflow_resolution/Move.exp @@ -37,6 +37,7 @@ CompiledPackageInfo { compiler_version: Some( V1, ), + language_version: None, }, }, } diff --git a/third_party/move/tools/move-package/tests/test_sources/compilation/diamond_problem_no_conflict/Move.exp b/third_party/move/tools/move-package/tests/test_sources/compilation/diamond_problem_no_conflict/Move.exp index 5194ca1a281b1..14caf20ea4a78 100644 --- a/third_party/move/tools/move-package/tests/test_sources/compilation/diamond_problem_no_conflict/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/compilation/diamond_problem_no_conflict/Move.exp @@ -37,6 +37,7 @@ CompiledPackageInfo { compiler_version: Some( V1, ), + language_version: None, }, }, } diff --git a/third_party/move/tools/move-package/tests/test_sources/compilation/multiple_deps_rename/Move.exp b/third_party/move/tools/move-package/tests/test_sources/compilation/multiple_deps_rename/Move.exp index bb47cd6d05d60..08b31aacb2e40 100644 --- a/third_party/move/tools/move-package/tests/test_sources/compilation/multiple_deps_rename/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/compilation/multiple_deps_rename/Move.exp @@ -38,6 +38,7 @@ CompiledPackageInfo { compiler_version: Some( V1, ), + language_version: None, }, }, } diff --git a/third_party/move/tools/move-package/tests/test_sources/compilation/multiple_deps_rename_one/Move.exp b/third_party/move/tools/move-package/tests/test_sources/compilation/multiple_deps_rename_one/Move.exp index e50985f2f2724..4951314aa0ea8 100644 --- a/third_party/move/tools/move-package/tests/test_sources/compilation/multiple_deps_rename_one/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/compilation/multiple_deps_rename_one/Move.exp @@ -38,6 +38,7 @@ CompiledPackageInfo { compiler_version: Some( V1, ), + language_version: None, }, }, } diff --git a/third_party/move/tools/move-package/tests/test_sources/compilation/one_dep/Move.exp b/third_party/move/tools/move-package/tests/test_sources/compilation/one_dep/Move.exp index 67e3d2a1f155e..6197567116d6a 100644 --- a/third_party/move/tools/move-package/tests/test_sources/compilation/one_dep/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/compilation/one_dep/Move.exp @@ -36,6 +36,7 @@ CompiledPackageInfo { compiler_version: Some( V1, ), + language_version: None, }, }, } diff --git a/third_party/move/tools/move-package/tests/test_sources/compilation/one_dep_assigned_address/Move.exp b/third_party/move/tools/move-package/tests/test_sources/compilation/one_dep_assigned_address/Move.exp index e2a79584ebe18..b739c18644d23 100644 --- a/third_party/move/tools/move-package/tests/test_sources/compilation/one_dep_assigned_address/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/compilation/one_dep_assigned_address/Move.exp @@ -36,6 +36,7 @@ CompiledPackageInfo { compiler_version: Some( V1, ), + language_version: None, }, }, } diff --git a/third_party/move/tools/move-package/tests/test_sources/compilation/one_dep_renamed/Move.exp b/third_party/move/tools/move-package/tests/test_sources/compilation/one_dep_renamed/Move.exp index 67e3d2a1f155e..6197567116d6a 100644 --- a/third_party/move/tools/move-package/tests/test_sources/compilation/one_dep_renamed/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/compilation/one_dep_renamed/Move.exp @@ -36,6 +36,7 @@ CompiledPackageInfo { compiler_version: Some( V1, ), + language_version: None, }, }, } diff --git a/third_party/move/tools/move-package/tests/test_sources/compilation/one_dep_with_scripts/Move.exp b/third_party/move/tools/move-package/tests/test_sources/compilation/one_dep_with_scripts/Move.exp index 67e3d2a1f155e..6197567116d6a 100644 --- a/third_party/move/tools/move-package/tests/test_sources/compilation/one_dep_with_scripts/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/compilation/one_dep_with_scripts/Move.exp @@ -36,6 +36,7 @@ CompiledPackageInfo { compiler_version: Some( V1, ), + language_version: None, }, }, } diff --git a/third_party/move/tools/move-package/tests/test_sources/compilation/test_symlinks/Move.exp b/third_party/move/tools/move-package/tests/test_sources/compilation/test_symlinks/Move.exp index abc4820b4b8d0..7719a13c2b504 100644 --- a/third_party/move/tools/move-package/tests/test_sources/compilation/test_symlinks/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/compilation/test_symlinks/Move.exp @@ -36,6 +36,7 @@ CompiledPackageInfo { compiler_version: Some( V1, ), + language_version: None, }, }, } diff --git a/third_party/move/tools/move-package/tests/test_sources/parsing/invalid_identifier_package_name/Move.exp b/third_party/move/tools/move-package/tests/test_sources/parsing/invalid_identifier_package_name/Move.exp index 29dc4156ad3b2..7e24cce41b587 100644 --- a/third_party/move/tools/move-package/tests/test_sources/parsing/invalid_identifier_package_name/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/parsing/invalid_identifier_package_name/Move.exp @@ -30,6 +30,7 @@ ResolutionGraph { compiler_version: Some( V1, ), + language_version: None, }, }, root_package: SourceManifest { diff --git a/third_party/move/tools/move-package/tests/test_sources/parsing/minimal_manifest/Move.exp b/third_party/move/tools/move-package/tests/test_sources/parsing/minimal_manifest/Move.exp index 606e23cb8fb4c..d9a9a2eb11344 100644 --- a/third_party/move/tools/move-package/tests/test_sources/parsing/minimal_manifest/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/parsing/minimal_manifest/Move.exp @@ -30,6 +30,7 @@ ResolutionGraph { compiler_version: Some( V1, ), + language_version: None, }, }, root_package: SourceManifest { diff --git a/third_party/move/tools/move-package/tests/test_sources/resolution/basic_no_deps/Move.exp b/third_party/move/tools/move-package/tests/test_sources/resolution/basic_no_deps/Move.exp index 1a4b431008633..c7a32db370932 100644 --- a/third_party/move/tools/move-package/tests/test_sources/resolution/basic_no_deps/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/resolution/basic_no_deps/Move.exp @@ -30,6 +30,7 @@ ResolutionGraph { compiler_version: Some( V1, ), + language_version: None, }, }, root_package: SourceManifest { diff --git a/third_party/move/tools/move-package/tests/test_sources/resolution/basic_no_deps_address_assigned/Move.exp b/third_party/move/tools/move-package/tests/test_sources/resolution/basic_no_deps_address_assigned/Move.exp index 59dcd290a9bd9..f2173a630b7ae 100644 --- a/third_party/move/tools/move-package/tests/test_sources/resolution/basic_no_deps_address_assigned/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/resolution/basic_no_deps_address_assigned/Move.exp @@ -30,6 +30,7 @@ ResolutionGraph { compiler_version: Some( V1, ), + language_version: None, }, }, root_package: SourceManifest { diff --git a/third_party/move/tools/move-package/tests/test_sources/resolution/basic_no_deps_address_not_assigned_with_dev_assignment/Move.exp b/third_party/move/tools/move-package/tests/test_sources/resolution/basic_no_deps_address_not_assigned_with_dev_assignment/Move.exp index 63305bf4697be..8323aebec23be 100644 --- a/third_party/move/tools/move-package/tests/test_sources/resolution/basic_no_deps_address_not_assigned_with_dev_assignment/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/resolution/basic_no_deps_address_not_assigned_with_dev_assignment/Move.exp @@ -30,6 +30,7 @@ ResolutionGraph { compiler_version: Some( V1, ), + language_version: None, }, }, root_package: SourceManifest { diff --git a/third_party/move/tools/move-package/tests/test_sources/resolution/dep_good_digest/Move.exp b/third_party/move/tools/move-package/tests/test_sources/resolution/dep_good_digest/Move.exp index 26ff5c843afd9..14d3339915f56 100644 --- a/third_party/move/tools/move-package/tests/test_sources/resolution/dep_good_digest/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/resolution/dep_good_digest/Move.exp @@ -30,6 +30,7 @@ ResolutionGraph { compiler_version: Some( V1, ), + language_version: None, }, }, root_package: SourceManifest { diff --git a/third_party/move/tools/move-package/tests/test_sources/resolution/diamond_problem_backflow_resolution/Move.exp b/third_party/move/tools/move-package/tests/test_sources/resolution/diamond_problem_backflow_resolution/Move.exp index c29c1a9f59014..daeee0be6a2b4 100644 --- a/third_party/move/tools/move-package/tests/test_sources/resolution/diamond_problem_backflow_resolution/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/resolution/diamond_problem_backflow_resolution/Move.exp @@ -30,6 +30,7 @@ ResolutionGraph { compiler_version: Some( V1, ), + language_version: None, }, }, root_package: SourceManifest { diff --git a/third_party/move/tools/move-package/tests/test_sources/resolution/diamond_problem_no_conflict/Move.exp b/third_party/move/tools/move-package/tests/test_sources/resolution/diamond_problem_no_conflict/Move.exp index e0d1adf994388..7a12b7249fe8e 100644 --- a/third_party/move/tools/move-package/tests/test_sources/resolution/diamond_problem_no_conflict/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/resolution/diamond_problem_no_conflict/Move.exp @@ -30,6 +30,7 @@ ResolutionGraph { compiler_version: Some( V1, ), + language_version: None, }, }, root_package: SourceManifest { diff --git a/third_party/move/tools/move-package/tests/test_sources/resolution/multiple_deps_rename/Move.exp b/third_party/move/tools/move-package/tests/test_sources/resolution/multiple_deps_rename/Move.exp index cfe74d8e285a6..930b16d46aef9 100644 --- a/third_party/move/tools/move-package/tests/test_sources/resolution/multiple_deps_rename/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/resolution/multiple_deps_rename/Move.exp @@ -30,6 +30,7 @@ ResolutionGraph { compiler_version: Some( V1, ), + language_version: None, }, }, root_package: SourceManifest { diff --git a/third_party/move/tools/move-package/tests/test_sources/resolution/one_dep/Move.exp b/third_party/move/tools/move-package/tests/test_sources/resolution/one_dep/Move.exp index d77da04ad6c9e..d27f5a7a508ae 100644 --- a/third_party/move/tools/move-package/tests/test_sources/resolution/one_dep/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/resolution/one_dep/Move.exp @@ -30,6 +30,7 @@ ResolutionGraph { compiler_version: Some( V1, ), + language_version: None, }, }, root_package: SourceManifest { diff --git a/third_party/move/tools/move-package/tests/test_sources/resolution/one_dep_assigned_address/Move.exp b/third_party/move/tools/move-package/tests/test_sources/resolution/one_dep_assigned_address/Move.exp index 3da34c4251071..3d7ded2cd6d62 100644 --- a/third_party/move/tools/move-package/tests/test_sources/resolution/one_dep_assigned_address/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/resolution/one_dep_assigned_address/Move.exp @@ -30,6 +30,7 @@ ResolutionGraph { compiler_version: Some( V1, ), + language_version: None, }, }, root_package: SourceManifest { diff --git a/third_party/move/tools/move-package/tests/test_sources/resolution/one_dep_multiple_of_same_name/Move.exp b/third_party/move/tools/move-package/tests/test_sources/resolution/one_dep_multiple_of_same_name/Move.exp index bbd4403872d2f..75a513d49cea0 100644 --- a/third_party/move/tools/move-package/tests/test_sources/resolution/one_dep_multiple_of_same_name/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/resolution/one_dep_multiple_of_same_name/Move.exp @@ -30,6 +30,7 @@ ResolutionGraph { compiler_version: Some( V1, ), + language_version: None, }, }, root_package: SourceManifest { diff --git a/third_party/move/tools/move-package/tests/test_sources/resolution/one_dep_reassigned_address/Move.exp b/third_party/move/tools/move-package/tests/test_sources/resolution/one_dep_reassigned_address/Move.exp index 02cff20f9066d..a35b649a97837 100644 --- a/third_party/move/tools/move-package/tests/test_sources/resolution/one_dep_reassigned_address/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/resolution/one_dep_reassigned_address/Move.exp @@ -30,6 +30,7 @@ ResolutionGraph { compiler_version: Some( V1, ), + language_version: None, }, }, root_package: SourceManifest { diff --git a/third_party/move/tools/move-package/tests/test_sources/resolution/one_dep_unification_across_local_renamings/Move.exp b/third_party/move/tools/move-package/tests/test_sources/resolution/one_dep_unification_across_local_renamings/Move.exp index c0001f10c414b..29f0a821f714c 100644 --- a/third_party/move/tools/move-package/tests/test_sources/resolution/one_dep_unification_across_local_renamings/Move.exp +++ b/third_party/move/tools/move-package/tests/test_sources/resolution/one_dep_unification_across_local_renamings/Move.exp @@ -30,6 +30,7 @@ ResolutionGraph { compiler_version: Some( V1, ), + language_version: None, }, }, root_package: SourceManifest { From 99e664c6abd37157fad0a37ad32731b0266ac7f4 Mon Sep 17 00:00:00 2001 From: Alden Hu Date: Thu, 4 Apr 2024 12:18:42 -0700 Subject: [PATCH 05/36] relex failure threshold for pos_to_prop (#12679) --- testsuite/forge-cli/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/forge-cli/src/main.rs b/testsuite/forge-cli/src/main.rs index 462828e716a94..bccb4797f078f 100644 --- a/testsuite/forge-cli/src/main.rs +++ b/testsuite/forge-cli/src/main.rs @@ -1052,7 +1052,7 @@ fn realistic_env_workload_sweep_test() -> ForgeConfig { criteria: [ (5500, 100, 0.3, 0.3, 0.8, 0.65), (4500, 100, 0.3, 0.4, 1.0, 2.0), - (2000, 300, 0.3, 0.3, 0.8, 2.0), + (2000, 300, 0.3, 0.8, 0.8, 2.0), (600, 500, 0.3, 0.3, 0.8, 2.0), // (150, 0.5, 1.0, 1.5, 0.65), ] From d4ced6e405fe57d36b97abbac2ca58ac0fcf49e9 Mon Sep 17 00:00:00 2001 From: Teng Zhang Date: Thu, 4 Apr 2024 13:25:53 -0700 Subject: [PATCH 06/36] [Compiler-v2] Treat unit as tuple in type constraints (#12794) * fix unit * refactor --- .../checking/typing/assign_wrong_arity.exp | 18 ++++++++++++++---- .../checking/typing/assign_wrong_type.exp | 8 ++++++++ .../tests/checking/typing/bind_wrong_arity.exp | 8 ++++++++ .../tests/checking/typing/bind_wrong_type.exp | 16 ++++++++++++++++ .../checking/typing/declare_wrong_arity.exp | 8 ++++++++ .../tests/checking/typing/eq_invalid.exp | 8 ++++++++ .../tests/checking/typing/lambda.exp | 11 ++++++++--- .../checking/typing/loop_body_invalid.exp | 6 +++--- .../typing/loop_result_type_invalid.exp | 8 ++++++++ .../tests/checking/typing/neq_invalid.exp | 8 ++++++++ .../tests/checking/typing/pack_unit.exp | 12 ++++++++++++ .../tests/checking/typing/pack_unit.move | 7 +++++++ .../typing/vector_with_non_base_type.exp | 8 ++++++++ .../vector_with_non_base_type_inferred.exp | 8 ++++++++ .../checking/typing/while_body_invalid.exp | 6 +++--- .../move/move-compiler-v2/tests/v1.matched | 1 + .../move/move-compiler-v2/tests/v1.unmatched | 1 - third_party/move/move-model/src/ty.rs | 15 ++++++++++++++- 18 files changed, 142 insertions(+), 15 deletions(-) create mode 100644 third_party/move/move-compiler-v2/tests/checking/typing/pack_unit.exp create mode 100644 third_party/move/move-compiler-v2/tests/checking/typing/pack_unit.move diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/assign_wrong_arity.exp b/third_party/move/move-compiler-v2/tests/checking/typing/assign_wrong_arity.exp index eb237883b18be..08ce0758b4f21 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/assign_wrong_arity.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/assign_wrong_arity.exp @@ -1,10 +1,20 @@ Diagnostics: -error: the left-hand side has 0 items but the right-hand side provided 3 - ┌─ tests/checking/typing/assign_wrong_arity.move:7:9 +error: tuple type `()` is not allowed as a local variable type + ┌─ tests/checking/typing/assign_wrong_arity.move:5:13 │ -7 │ x = (0, 1, 2); - │ ^ +5 │ let x; + │ ^ + │ + = required by declaration of local `x` + +error: tuple type `(integer, integer, integer)` is not allowed as a local variable type + ┌─ tests/checking/typing/assign_wrong_arity.move:5:13 + │ +5 │ let x; + │ ^ + │ + = required by declaration of local `x` error: cannot assign `integer` to left-hand side of type `()` ┌─ tests/checking/typing/assign_wrong_arity.move:8:9 diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/assign_wrong_type.exp b/third_party/move/move-compiler-v2/tests/checking/typing/assign_wrong_type.exp index c82ace5112445..88451a26d014b 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/assign_wrong_type.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/assign_wrong_type.exp @@ -12,6 +12,14 @@ error: cannot assign `R` to left-hand side of type `S` 9 │ (S { g }, R { f }) = (R{ f: 0 }, R{ f: 1 }); │ ^^^^^^^ +error: tuple type `()` is not allowed as a local variable type + ┌─ tests/checking/typing/assign_wrong_type.move:13:13 + │ +13 │ let x; + │ ^ + │ + = required by declaration of local `x` + error: cannot assign `integer` to left-hand side of type `()` ┌─ tests/checking/typing/assign_wrong_type.move:17:9 │ diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/bind_wrong_arity.exp b/third_party/move/move-compiler-v2/tests/checking/typing/bind_wrong_arity.exp index 5360c928663fc..0362598362c3a 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/bind_wrong_arity.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/bind_wrong_arity.exp @@ -1,5 +1,13 @@ Diagnostics: +error: tuple type `()` is not allowed as a local variable type + ┌─ tests/checking/typing/bind_wrong_arity.move:5:13 + │ +5 │ let x: () = (); + │ ^ + │ + = required by declaration of local `x` + error: cannot bind `u64` to left-hand side of type `()` ┌─ tests/checking/typing/bind_wrong_arity.move:6:13 │ diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/bind_wrong_type.exp b/third_party/move/move-compiler-v2/tests/checking/typing/bind_wrong_type.exp index 7d6c8f34f3813..19112ac4c8390 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/bind_wrong_type.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/bind_wrong_type.exp @@ -12,6 +12,14 @@ error: cannot bind `R` to left-hand side of type `S` 7 │ let (S { g }, R { f }) = (R{ f: 0 }, R{ f: 1 }); │ ^^^^^^^ +error: tuple type `()` is not allowed as a local variable type + ┌─ tests/checking/typing/bind_wrong_type.move:11:13 + │ +11 │ let x = (); + │ ^ + │ + = required by declaration of local `x` + error: cannot bind `integer` to left-hand side of type `()` ┌─ tests/checking/typing/bind_wrong_type.move:12:13 │ @@ -30,6 +38,14 @@ error: the left-hand side has 3 items but the right-hand side provided 2 14 │ let (x, b, R{f}) = (0, false); │ ^^^^^^^^^^^^ +error: tuple type `()` is not allowed as a local variable type + ┌─ tests/checking/typing/bind_wrong_type.move:18:13 + │ +18 │ let x: () = 0; + │ ^ + │ + = required by declaration of local `x` + error: cannot adapt `integer` to annotated type `()` ┌─ tests/checking/typing/bind_wrong_type.move:18:21 │ diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/declare_wrong_arity.exp b/third_party/move/move-compiler-v2/tests/checking/typing/declare_wrong_arity.exp index e8de23a7014bf..c92108a629765 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/declare_wrong_arity.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/declare_wrong_arity.exp @@ -1,5 +1,13 @@ Diagnostics: +error: tuple type `()` is not allowed as a local variable type + ┌─ tests/checking/typing/declare_wrong_arity.move:5:13 + │ +5 │ let x: (); + │ ^ + │ + = required by declaration of local `x` + error: cannot adapt `()` to annotated type `u64` ┌─ tests/checking/typing/declare_wrong_arity.move:6:13 │ diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/eq_invalid.exp b/third_party/move/move-compiler-v2/tests/checking/typing/eq_invalid.exp index c4809904b3310..bddddda5a5cec 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/eq_invalid.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/eq_invalid.exp @@ -46,6 +46,14 @@ error: unable to infer instantiation of type `G2<_>` (consider providing type ar 28 │ G2{} == G2{}; │ ^^^^ +error: tuple type `()` is not allowed as a type argument (type was inferred) + ┌─ tests/checking/typing/eq_invalid.move:33:12 + │ +33 │ () == (); + │ ^^ + │ + = required by instantiating type parameter `T` of function `==` + error: tuple type `(integer, integer)` is not allowed as a type argument (type was inferred) ┌─ tests/checking/typing/eq_invalid.move:34:16 │ diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/lambda.exp b/third_party/move/move-compiler-v2/tests/checking/typing/lambda.exp index 358de21e484c1..c3d568872e95c 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/lambda.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/lambda.exp @@ -38,8 +38,13 @@ error: reference type `&integer` is not allowed as a type argument (type was inf │ = required by instantiating type parameter `T` of function `+` -error: cannot pass `|&integer|integer` to a function which expects argument of type `|&integer|` - ┌─ tests/checking/typing/lambda.move:73:21 +error: tuple type `()` is not allowed as a type argument (type was inferred) + ┌─ tests/checking/typing/lambda.move:73:37 │ + 4 │ public inline fun foreach(v: &vector, action: |&T|) { // expected to be not implemented + │ - declaration of type parameter `T` + · 73 │ foreach(&v, |e| { sum = sum + *e; *e }) // expected to have wrong result type of lambda - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^ + │ ^ + │ + = required by instantiating type parameter `T` of function `foreach` diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/loop_body_invalid.exp b/third_party/move/move-compiler-v2/tests/checking/typing/loop_body_invalid.exp index d3fcdf9b85db5..8738c6b8adceb 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/loop_body_invalid.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/loop_body_invalid.exp @@ -18,11 +18,11 @@ error: expected expression with no value but found `address` 11 │ loop { @0x0 } │ ^^^^ -error: expected expression with no value but found `integer` - ┌─ tests/checking/typing/loop_body_invalid.move:15:27 +error: tuple type `()` is not allowed + ┌─ tests/checking/typing/loop_body_invalid.move:15:20 │ 15 │ loop { let x = 0; x } - │ ^ + │ ^ error: expected expression with no value but found `integer` ┌─ tests/checking/typing/loop_body_invalid.move:19:26 diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/loop_result_type_invalid.exp b/third_party/move/move-compiler-v2/tests/checking/typing/loop_result_type_invalid.exp index 44ad429f705d7..a589c3fed8243 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/loop_result_type_invalid.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/loop_result_type_invalid.exp @@ -18,6 +18,14 @@ error: cannot pass `()` to a function which expects argument of type `u64` 19 │ foo(loop { break }) │ ^^^^^^^^^^^^^^ +error: tuple type `()` is not allowed as a local variable type + ┌─ tests/checking/typing/loop_result_type_invalid.move:25:13 + │ +25 │ let x = loop { break }; + │ ^ + │ + = required by declaration of local `x` + error: the left-hand side has 2 items but the right-hand side provided 0 ┌─ tests/checking/typing/loop_result_type_invalid.move:26:13 │ diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/neq_invalid.exp b/third_party/move/move-compiler-v2/tests/checking/typing/neq_invalid.exp index 9083227851781..91a3ffa5997c1 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/neq_invalid.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/neq_invalid.exp @@ -58,6 +58,14 @@ error: unable to infer instantiation of type `G2<_>` (consider providing type ar 28 │ G2{} != G2{}; │ ^^^^ +error: tuple type `()` is not allowed as a type argument (type was inferred) + ┌─ tests/checking/typing/neq_invalid.move:32:12 + │ +32 │ () != (); + │ ^^ + │ + = required by instantiating type parameter `T` of function `!=` + error: tuple type `(integer, integer)` is not allowed as a type argument (type was inferred) ┌─ tests/checking/typing/neq_invalid.move:33:16 │ diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/pack_unit.exp b/third_party/move/move-compiler-v2/tests/checking/typing/pack_unit.exp new file mode 100644 index 0000000000000..86eecd56e4aa6 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/typing/pack_unit.exp @@ -0,0 +1,12 @@ + +Diagnostics: +error: tuple type `()` is not allowed as a type argument (type was inferred) + ┌─ tests/checking/typing/pack_unit.move:5:9 + │ +2 │ struct Box has drop { f: T } + │ - declaration of type parameter `T` + · +5 │ Box { f: () }; + │ ^^^ + │ + = required by instantiating type parameter `T` of struct `Box` diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/pack_unit.move b/third_party/move/move-compiler-v2/tests/checking/typing/pack_unit.move new file mode 100644 index 0000000000000..e9d956c8c921c --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/typing/pack_unit.move @@ -0,0 +1,7 @@ +module 0x8675309::M { + struct Box has drop { f: T } + + fun t0() { + Box { f: () }; + } +} diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/vector_with_non_base_type.exp b/third_party/move/move-compiler-v2/tests/checking/typing/vector_with_non_base_type.exp index 94a34dda4609a..5108015d4c6b9 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/vector_with_non_base_type.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/vector_with_non_base_type.exp @@ -16,6 +16,14 @@ error: reference type `&mut u64` is not allowed as a type argument │ = required by instantiating vector type parameter +error: tuple type `()` is not allowed as a type argument + ┌─ tests/checking/typing/vector_with_non_base_type.move:6:24 + │ +6 │ let v = vector<()>[]; + │ ^^ + │ + = required by instantiating vector type parameter + error: tuple type `(u64, bool)` is not allowed as a type argument ┌─ tests/checking/typing/vector_with_non_base_type.move:7:24 │ diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/vector_with_non_base_type_inferred.exp b/third_party/move/move-compiler-v2/tests/checking/typing/vector_with_non_base_type_inferred.exp index 87741319195fe..f83fdd9d7f343 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/vector_with_non_base_type_inferred.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/vector_with_non_base_type_inferred.exp @@ -16,6 +16,14 @@ error: reference type `&mut integer` is not allowed as a type argument (type was │ = required by instantiating vector type parameter +error: tuple type `()` is not allowed as a type argument (type was inferred) + ┌─ tests/checking/typing/vector_with_non_base_type_inferred.move:6:9 + │ +6 │ vector[()]; + │ ^^^^^^ + │ + = required by instantiating vector type parameter + error: tuple type `(integer, bool)` is not allowed as a type argument (type was inferred) ┌─ tests/checking/typing/vector_with_non_base_type_inferred.move:7:9 │ diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/while_body_invalid.exp b/third_party/move/move-compiler-v2/tests/checking/typing/while_body_invalid.exp index 9fea8ca0dd036..f8e536706d99a 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/while_body_invalid.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/while_body_invalid.exp @@ -18,11 +18,11 @@ error: expected expression with no value but found `address` 5 │ while (cond) { @0x0 }; │ ^^^^ -error: expected expression with no value but found `integer` - ┌─ tests/checking/typing/while_body_invalid.move:6:35 +error: tuple type `()` is not allowed + ┌─ tests/checking/typing/while_body_invalid.move:6:28 │ 6 │ while (cond) { let x = 0; x }; - │ ^ + │ ^ error: expected expression with no value but found `integer` ┌─ tests/checking/typing/while_body_invalid.move:7:34 diff --git a/third_party/move/move-compiler-v2/tests/v1.matched b/third_party/move/move-compiler-v2/tests/v1.matched index 4bc14fbc1c1f2..5d6a27b19b399 100644 --- a/third_party/move/move-compiler-v2/tests/v1.matched +++ b/third_party/move/move-compiler-v2/tests/v1.matched @@ -364,6 +364,7 @@ move-compiler/tests/move_check/typing/pack_invalid_argument.exp move-compiler- move-compiler/tests/move_check/typing/pack_missing_field.exp move-compiler-v2/tests/checking/typing/pack_missing_field.exp move-compiler/tests/move_check/typing/pack_multiple.exp move-compiler-v2/tests/checking/typing/pack_multiple.exp move-compiler/tests/move_check/typing/pack_reference.exp move-compiler-v2/tests/checking/typing/pack_reference.exp +move-compiler/tests/move_check/typing/pack_unit.exp move-compiler-v2/tests/checking/typing/pack_unit.exp move-compiler/tests/move_check/typing/phantom_param_op_abilities.exp move-compiler-v2/tests/checking/abilities/v1/phantom_param_op_abilities.exp move-compiler/tests/move_check/typing/phantom_param_op_abilities_invalid.exp move-compiler-v2/tests/checking/abilities/v1/phantom_param_op_abilities_invalid.exp move-compiler/tests/move_check/typing/phantom_params_constraint_abilities.exp move-compiler-v2/tests/checking/abilities/v1/phantom_params_constraint_abilities.exp diff --git a/third_party/move/move-compiler-v2/tests/v1.unmatched b/third_party/move/move-compiler-v2/tests/v1.unmatched index 4ed6bf2055f0d..7a59477e16b97 100644 --- a/third_party/move/move-compiler-v2/tests/v1.unmatched +++ b/third_party/move/move-compiler-v2/tests/v1.unmatched @@ -206,7 +206,6 @@ move-compiler/tests/move_check/typing/{ non_phantom_in_phantom_pos.move, pack_constraint_not_satisfied.move, pack_private_with_field.move, - pack_unit.move, pack_unpack_private.move, pack_unpack_private_script.move, pay_me_a_river.move, diff --git a/third_party/move/move-model/src/ty.rs b/third_party/move/move-model/src/ty.rs index 2993940d935cc..cf73652dd2434 100644 --- a/third_party/move/move-model/src/ty.rs +++ b/third_party/move/move-model/src/ty.rs @@ -1313,9 +1313,14 @@ impl Type { } /// If this is a tuple and it is not a unit type, return true. - pub fn is_tuple(&self) -> bool { + pub fn is_non_unit_tuple(&self) -> bool { matches!(self, Type::Tuple(ts) if !ts.is_empty()) } + + /// If this is a tuple, return true. + pub fn is_tuple(&self) -> bool { + matches!(self, Type::Tuple(_)) + } } /// A parameter for type unification that specifies the type compatibility rules to follow. @@ -2796,6 +2801,14 @@ impl TypeUnificationError { origin: ConstraintOrigin::Local(_), .. }) => "as a local variable type", + Some(ConstraintContext { + origin: ConstraintOrigin::Unspecified, + .. + }) => "", + Some(ConstraintContext { + origin: ConstraintOrigin::TupleElement(_, _), + .. + }) => "as a tuple element", _ => "as a type argument", }; let (mut note, mut hints, mut labels) = ctx_opt From 446cdfc967907ba90824e6e825f220f02b8f2468 Mon Sep 17 00:00:00 2001 From: Stelian Ionescu Date: Thu, 4 Apr 2024 15:14:16 -0400 Subject: [PATCH 07/36] [GH] Update version of GCloud actions Also upgrade actions/checkout to v4. --- .github/actions/docker-setup/action.yaml | 5 ++--- .github/workflows/cargo-metadata-upload.yaml | 6 +++--- .github/workflows/copy-images-to-dockerhub.yaml | 2 +- .github/workflows/docker-update-images.yaml | 2 +- .github/workflows/workflow-run-forge.yaml | 4 ++-- .github/workflows/workflow-run-replay-verify.yaml | 10 +++++----- 6 files changed, 14 insertions(+), 15 deletions(-) diff --git a/.github/actions/docker-setup/action.yaml b/.github/actions/docker-setup/action.yaml index c62df21a2ccc8..4cc0ea02bf4d8 100644 --- a/.github/actions/docker-setup/action.yaml +++ b/.github/actions/docker-setup/action.yaml @@ -36,10 +36,9 @@ inputs: required: false GCP_AUTH_DURATION: description: "Duration of GCP auth token in seconds" - type: int # setting this to 1.5h since sometimes docker builds (special performance # builds etc.) take that long. Default is 1h. - default: 5400 + default: "5400" outputs: CLOUDSDK_AUTH_ACCESS_TOKEN: @@ -78,7 +77,7 @@ runs: - id: auth name: "Authenticate to Google Cloud" - uses: "google-github-actions/auth@v1" + uses: "google-github-actions/auth@v2" with: create_credentials_file: false token_format: "access_token" diff --git a/.github/workflows/cargo-metadata-upload.yaml b/.github/workflows/cargo-metadata-upload.yaml index 7013fdf3e5a35..f6654df475540 100644 --- a/.github/workflows/cargo-metadata-upload.yaml +++ b/.github/workflows/cargo-metadata-upload.yaml @@ -13,14 +13,14 @@ jobs: cargo-metadata: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dsherret/rust-toolchain-file@v1 - id: auth - uses: "google-github-actions/auth@v1" + uses: "google-github-actions/auth@v2" with: workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GCP_SERVICE_ACCOUNT_EMAIL }} - - uses: "google-github-actions/setup-gcloud@v1" + - uses: "google-github-actions/setup-gcloud@v2" - shell: bash run: | cargo metadata --all-features | gsutil cp - gs://aptos-core-cargo-metadata-public/metadata-${{ github.sha }}.json diff --git a/.github/workflows/copy-images-to-dockerhub.yaml b/.github/workflows/copy-images-to-dockerhub.yaml index 2e81a1df824c6..b2c11a156c6e1 100644 --- a/.github/workflows/copy-images-to-dockerhub.yaml +++ b/.github/workflows/copy-images-to-dockerhub.yaml @@ -31,7 +31,7 @@ jobs: # Run on a machine with more local storage for large docker images runs-on: medium-perf-docker-with-local-ssd steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: aptos-labs/aptos-core/.github/actions/docker-setup@main with: diff --git a/.github/workflows/docker-update-images.yaml b/.github/workflows/docker-update-images.yaml index 21415b2257bce..8bebefaae93b7 100644 --- a/.github/workflows/docker-update-images.yaml +++ b/.github/workflows/docker-update-images.yaml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Login to Docker Hub uses: docker/login-action@v2 diff --git a/.github/workflows/workflow-run-forge.yaml b/.github/workflows/workflow-run-forge.yaml index 26c1b76b2c3bf..5de05cc005469 100644 --- a/.github/workflows/workflow-run-forge.yaml +++ b/.github/workflows/workflow-run-forge.yaml @@ -107,7 +107,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: ${{ inputs.TIMEOUT_MINUTES }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 if: ${{ !inputs.SKIP_JOB }} with: ref: ${{ inputs.GIT_SHA }} @@ -152,7 +152,7 @@ jobs: - name: "Install GCloud SDK" if: ${{ !inputs.SKIP_JOB }} - uses: "google-github-actions/setup-gcloud@v1" + uses: "google-github-actions/setup-gcloud@v2" with: version: ">= 418.0.0" install_components: "kubectl,gke-gcloud-auth-plugin" diff --git a/.github/workflows/workflow-run-replay-verify.yaml b/.github/workflows/workflow-run-replay-verify.yaml index 01499e0f6ec77..acf1a809ec695 100644 --- a/.github/workflows/workflow-run-replay-verify.yaml +++ b/.github/workflows/workflow-run-replay-verify.yaml @@ -81,13 +81,13 @@ jobs: timeout-minutes: ${{ inputs.TIMEOUT_MINUTES || 720 }} runs-on: ${{ inputs.RUNS_ON }} strategy: - fail-fast: false - matrix: - number: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] # runner number + fail-fast: false + matrix: + number: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] # runner number steps: - name: Echo Runner Number run: echo "Runner is ${{ matrix.number }}" - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: ${{ inputs.GIT_SHA }} @@ -96,7 +96,7 @@ jobs: GIT_CREDENTIALS: ${{ secrets.GIT_CREDENTIALS }} - name: Install GCloud SDK - uses: "google-github-actions/setup-gcloud@62d4898025f6041e16b1068643bfc5a696863587" # pin@v1 + uses: "google-github-actions/setup-gcloud@v2" with: version: ">= 418.0.0" install_components: "kubectl,gke-gcloud-auth-plugin" From 7b01dfab790a60e0ba5e073c2945ec48e1b7e9f2 Mon Sep 17 00:00:00 2001 From: "Brian R. Murphy" <132495859+brmataptos@users.noreply.github.com> Date: Thu, 4 Apr 2024 23:48:20 -0700 Subject: [PATCH 08/36] Add compile_test_code flag to V2, plus tests for unit_test, attributes, and skip_attribute_checks, along with testsuite changes (#12790) * add a config field options.compile_test_code to move-compiler-v2, receive it from tests, honor in module generation * add v2 tests for skip-attribute-checks flag and unit_tests (with test-mode on and off) * add attributes-related tests from V1 to V2 * unrelated: fix diem-framework code to build again to test v2 compile_test_code option --- .../src/file_format_generator/mod.rs | 13 ++- .../file_format_generator/module_generator.rs | 8 ++ third_party/move/move-compiler-v2/src/lib.rs | 1 + .../move/move-compiler-v2/src/options.rs | 17 +++ .../attributes/aptos_stdlib_attributes.exp | 49 ++++++++ .../attributes/aptos_stdlib_attributes.move | 10 ++ .../attributes/aptos_stdlib_attributes2.exp | 17 +++ .../attributes/aptos_stdlib_attributes2.move | 6 + .../attribute_no_closing_bracket.exp | 9 ++ .../attribute_no_closing_bracket.move | 5 + .../attribute_num_sign_no_bracket.exp | 10 ++ .../attribute_num_sign_no_bracket.move | 5 + .../attributes/attribute_placement.exp | 108 ++++++++++++++++++ .../attributes/attribute_placement.move | 46 ++++++++ .../attributes/attribute_variants.exp | 65 +++++++++++ .../attributes/attribute_variants.move | 6 + .../attributes/duplicate_attributes.exp | 43 +++++++ .../attributes/duplicate_attributes.move | 7 ++ .../aptos_stdlib_attributes.exp | 25 ++++ .../aptos_stdlib_attributes.move | 10 ++ .../aptos_stdlib_attributes2.move | 6 + .../attribute_no_closing_bracket.exp | 9 ++ .../attribute_no_closing_bracket.move | 5 + .../attribute_placement.move | 46 ++++++++ .../attribute_variants.move | 6 + .../duplicate_attributes.exp | 25 ++++ .../duplicate_attributes.move | 7 ++ .../extra_attributes.move | 26 +++++ .../extra_attributes2.move | 23 ++++ .../tests/skip_attribute_checks/testonly.move | 9 ++ .../move/move-compiler-v2/tests/testsuite.rs | 56 ++++++++- .../unit_test/notest/attribute_location.move | 33 ++++++ .../notest/attribute_location_invalid.exp | 16 +++ .../notest/attribute_location_invalid.move | 12 ++ .../notest/cross_module_members.move | 24 ++++ ...cross_module_members_non_test_function.exp | 7 ++ ...ross_module_members_non_test_function.move | 27 +++++ .../notest/cross_module_test_only_module.exp | 13 +++ .../notest/cross_module_test_only_module.move | 16 +++ .../notest/expected_failure_bad_value.move | 25 ++++ .../notest/expected_failure_constants.move | 33 ++++++ .../expected_failure_constants_invalid.move | 19 +++ .../expected_failure_invalid_literals.move | 21 ++++ .../notest/expected_failure_not_test.move | 8 ++ .../expected_failure_on_non_function.exp | 28 +++++ .../expected_failure_on_non_function.move | 13 +++ .../expected_failure_out_of_range_value.move | 19 +++ .../unit_test/notest/extra_attributes.move | 26 +++++ .../unit_test/notest/extra_attributes2.move | 23 ++++ .../notest/invalid_expected_code_name.move | 14 +++ .../notest/invalid_expected_failure_name.move | 6 + .../unit_test/notest/multiple_errors.move | 45 ++++++++ .../notest/multiple_test_annotations.move | 13 +++ .../named_address_no_value_in_annotation.move | 4 + .../other_failures_invalid_assignment.move | 32 ++++++ .../other_failures_invalid_location.move | 41 +++++++ ...ther_failures_invalid_location_module.move | 9 ++ .../notest/other_failures_valid.move | 27 +++++ .../notest/script_with_multiple_on_main.exp | 19 +++ .../notest/script_with_multiple_on_main.move | 7 ++ .../notest/script_with_multiple_top_level.exp | 19 +++ .../script_with_multiple_top_level.move | 7 ++ .../notest/script_with_test_on_main.exp | 7 ++ .../notest/script_with_test_on_main.move | 5 + .../notest/script_with_test_top_level.exp | 7 ++ .../notest/script_with_test_top_level.move | 5 + .../notest/test_and_test_only_annotation.move | 8 ++ .../unit_test/notest/test_filter_function.exp | 7 ++ .../notest/test_filter_function.move | 11 ++ .../unit_test/notest/test_filter_struct.exp | 13 +++ .../unit_test/notest/test_filter_struct.move | 13 +++ .../unit_test/notest/valid_test_module.move | 50 ++++++++ .../unit_test/test/attribute_location.move | 33 ++++++ .../test/attribute_location_invalid.exp | 25 ++++ .../test/attribute_location_invalid.move | 12 ++ .../unit_test/test/cross_module_members.move | 24 ++++ ...ross_module_members_non_test_function.move | 27 +++++ .../test/cross_module_test_only_module.move | 16 +++ .../test/expected_failure_bad_value.move | 25 ++++ .../test/expected_failure_constants.move | 33 ++++++ .../expected_failure_constants_invalid.move | 19 +++ .../expected_failure_invalid_literals.move | 21 ++++ .../test/expected_failure_not_test.move | 8 ++ .../test/expected_failure_on_non_function.exp | 28 +++++ .../expected_failure_on_non_function.move | 13 +++ .../expected_failure_out_of_range_value.move | 19 +++ .../unit_test/test/extra_attributes.move | 26 +++++ .../unit_test/test/extra_attributes2.exp | 25 ++++ .../unit_test/test/extra_attributes2.move | 23 ++++ .../test/invalid_expected_code_name.move | 14 +++ .../test/invalid_expected_failure_name.move | 6 + .../tests/unit_test/test/multiple_errors.exp | 17 +++ .../tests/unit_test/test/multiple_errors.move | 45 ++++++++ .../test/multiple_test_annotations.exp | 17 +++ .../test/multiple_test_annotations.move | 13 +++ .../named_address_no_value_in_annotation.exp | 7 ++ .../named_address_no_value_in_annotation.move | 4 + .../other_failures_invalid_assignment.move | 32 ++++++ .../test/other_failures_invalid_location.move | 41 +++++++ ...other_failures_invalid_location_module.exp | 7 ++ ...ther_failures_invalid_location_module.move | 9 ++ .../unit_test/test/other_failures_valid.move | 27 +++++ .../test/script_with_multiple_on_main.exp | 19 +++ .../test/script_with_multiple_on_main.move | 7 ++ .../test/script_with_multiple_top_level.exp | 19 +++ .../test/script_with_multiple_top_level.move | 7 ++ .../test/script_with_test_on_main.exp | 7 ++ .../test/script_with_test_on_main.move | 5 + .../test/script_with_test_top_level.exp | 7 ++ .../test/script_with_test_top_level.move | 5 + .../test/test_and_test_only_annotation.move | 8 ++ .../unit_test/test/test_filter_function.move | 11 ++ .../unit_test/test/test_filter_struct.move | 13 +++ .../unit_test/test/valid_test_module.move | 50 ++++++++ .../move/move-compiler-v2/tests/v1.matched | 31 +++++ .../move/move-compiler-v2/tests/v1.unmatched | 14 +++ .../parser/aptos_stdlib_attributes.move | 2 +- .../aptos_stdlib_attributes.move | 2 +- .../to_bytecode/unassigned_address.exp | 42 +++++++ .../to_bytecode/unassigned_address.move | 12 +- .../move-packages/core/Move.toml | 4 +- .../move-packages/experimental/Move.toml | 2 +- .../experimental/sources/MultiToken.move | 6 +- .../sources/MultiTokenBalance.move | 6 +- third_party/move/move-model/src/lib.rs | 5 +- third_party/move/move-prover/src/lib.rs | 4 +- .../src/compilation/compiled_package.rs | 1 + 127 files changed, 2290 insertions(+), 25 deletions(-) create mode 100644 third_party/move/move-compiler-v2/tests/checking/attributes/aptos_stdlib_attributes.exp create mode 100644 third_party/move/move-compiler-v2/tests/checking/attributes/aptos_stdlib_attributes.move create mode 100644 third_party/move/move-compiler-v2/tests/checking/attributes/aptos_stdlib_attributes2.exp create mode 100644 third_party/move/move-compiler-v2/tests/checking/attributes/aptos_stdlib_attributes2.move create mode 100644 third_party/move/move-compiler-v2/tests/checking/attributes/attribute_no_closing_bracket.exp create mode 100644 third_party/move/move-compiler-v2/tests/checking/attributes/attribute_no_closing_bracket.move create mode 100644 third_party/move/move-compiler-v2/tests/checking/attributes/attribute_num_sign_no_bracket.exp create mode 100644 third_party/move/move-compiler-v2/tests/checking/attributes/attribute_num_sign_no_bracket.move create mode 100644 third_party/move/move-compiler-v2/tests/checking/attributes/attribute_placement.exp create mode 100644 third_party/move/move-compiler-v2/tests/checking/attributes/attribute_placement.move create mode 100644 third_party/move/move-compiler-v2/tests/checking/attributes/attribute_variants.exp create mode 100644 third_party/move/move-compiler-v2/tests/checking/attributes/attribute_variants.move create mode 100644 third_party/move/move-compiler-v2/tests/checking/attributes/duplicate_attributes.exp create mode 100644 third_party/move/move-compiler-v2/tests/checking/attributes/duplicate_attributes.move create mode 100644 third_party/move/move-compiler-v2/tests/skip_attribute_checks/aptos_stdlib_attributes.exp create mode 100644 third_party/move/move-compiler-v2/tests/skip_attribute_checks/aptos_stdlib_attributes.move create mode 100644 third_party/move/move-compiler-v2/tests/skip_attribute_checks/aptos_stdlib_attributes2.move create mode 100644 third_party/move/move-compiler-v2/tests/skip_attribute_checks/attribute_no_closing_bracket.exp create mode 100644 third_party/move/move-compiler-v2/tests/skip_attribute_checks/attribute_no_closing_bracket.move create mode 100644 third_party/move/move-compiler-v2/tests/skip_attribute_checks/attribute_placement.move create mode 100644 third_party/move/move-compiler-v2/tests/skip_attribute_checks/attribute_variants.move create mode 100644 third_party/move/move-compiler-v2/tests/skip_attribute_checks/duplicate_attributes.exp create mode 100644 third_party/move/move-compiler-v2/tests/skip_attribute_checks/duplicate_attributes.move create mode 100644 third_party/move/move-compiler-v2/tests/skip_attribute_checks/extra_attributes.move create mode 100644 third_party/move/move-compiler-v2/tests/skip_attribute_checks/extra_attributes2.move create mode 100644 third_party/move/move-compiler-v2/tests/skip_attribute_checks/testonly.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/attribute_location.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/attribute_location_invalid.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/attribute_location_invalid.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/cross_module_members.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/cross_module_members_non_test_function.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/cross_module_members_non_test_function.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/cross_module_test_only_module.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/cross_module_test_only_module.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_bad_value.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_constants.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_constants_invalid.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_invalid_literals.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_not_test.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_on_non_function.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_on_non_function.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_out_of_range_value.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/extra_attributes.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/extra_attributes2.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/invalid_expected_code_name.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/invalid_expected_failure_name.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/multiple_errors.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/multiple_test_annotations.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/named_address_no_value_in_annotation.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_invalid_assignment.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_invalid_location.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_invalid_location_module.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_valid.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_multiple_on_main.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_multiple_on_main.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_multiple_top_level.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_multiple_top_level.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_test_on_main.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_test_on_main.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_test_top_level.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_test_top_level.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/test_and_test_only_annotation.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/test_filter_function.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/test_filter_function.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/test_filter_struct.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/test_filter_struct.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/valid_test_module.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/attribute_location.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/attribute_location_invalid.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/attribute_location_invalid.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/cross_module_members.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/cross_module_members_non_test_function.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/cross_module_test_only_module.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_bad_value.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_constants.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_constants_invalid.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_invalid_literals.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_not_test.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_on_non_function.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_on_non_function.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_out_of_range_value.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/extra_attributes.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/extra_attributes2.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/extra_attributes2.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/invalid_expected_code_name.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/invalid_expected_failure_name.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/multiple_errors.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/multiple_errors.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/multiple_test_annotations.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/multiple_test_annotations.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/named_address_no_value_in_annotation.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/named_address_no_value_in_annotation.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_invalid_assignment.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_invalid_location.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_invalid_location_module.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_invalid_location_module.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_valid.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/script_with_multiple_on_main.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/script_with_multiple_on_main.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/script_with_multiple_top_level.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/script_with_multiple_top_level.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/script_with_test_on_main.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/script_with_test_on_main.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/script_with_test_top_level.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/script_with_test_top_level.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/test_and_test_only_annotation.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/test_filter_function.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/test_filter_struct.move create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/valid_test_module.move create mode 100644 third_party/move/move-compiler/tests/move_check/to_bytecode/unassigned_address.exp diff --git a/third_party/move/move-compiler-v2/src/file_format_generator/mod.rs b/third_party/move/move-compiler-v2/src/file_format_generator/mod.rs index ba95929f3e09c..a44373a363a97 100644 --- a/third_party/move/move-compiler-v2/src/file_format_generator/mod.rs +++ b/third_party/move/move-compiler-v2/src/file_format_generator/mod.rs @@ -1,7 +1,10 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use crate::file_format_generator::module_generator::ModuleContext; +mod function_generator; +mod module_generator; + +use crate::{file_format_generator::module_generator::ModuleContext, options::Options}; use module_generator::ModuleGenerator; use move_binary_format::{file_format as FF, internals::ModuleIndex}; use move_command_line_common::{address::NumericalAddress, parser::NumberFormat}; @@ -10,19 +13,21 @@ use move_model::model::GlobalEnv; use move_stackless_bytecode::function_target_pipeline::FunctionTargetsHolder; use move_symbol_pool::Symbol; -mod function_generator; -mod module_generator; - pub fn generate_file_format( env: &GlobalEnv, targets: &FunctionTargetsHolder, ) -> Vec { let ctx = ModuleContext { env, targets }; let mut result = vec![]; + let options = env + .get_extension::() + .expect("Options is available"); + let compile_test_code = options.compile_test_code; for module_env in ctx.env.get_modules() { if !module_env.is_target() { continue; } + assert!(compile_test_code || !module_env.is_test_only()); let (ff_module, source_map, main_handle) = ModuleGenerator::run(&ctx, &module_env); if module_env.is_script_module() { let FF::CompiledModule { diff --git a/third_party/move/move-compiler-v2/src/file_format_generator/module_generator.rs b/third_party/move/move-compiler-v2/src/file_format_generator/module_generator.rs index d56ad9d498a5c..db480e9d6eb1f 100644 --- a/third_party/move/move-compiler-v2/src/file_format_generator/module_generator.rs +++ b/third_party/move/move-compiler-v2/src/file_format_generator/module_generator.rs @@ -156,12 +156,20 @@ impl ModuleGenerator { self.module_index(ctx, loc, module_env); } + let options = ctx + .env + .get_extension::() + .expect("Options is available"); + let compile_test_code = options.compile_test_code; + for struct_env in module_env.get_structs() { + assert!(compile_test_code || !struct_env.is_test_only()); self.gen_struct(ctx, &struct_env) } let acquires_map = ctx.generate_acquires_map(module_env); for fun_env in module_env.get_functions() { + assert!(compile_test_code || !fun_env.is_test_only()); let acquires_list = &acquires_map[&fun_env.get_id()]; FunctionGenerator::run(self, ctx, fun_env, acquires_list); } diff --git a/third_party/move/move-compiler-v2/src/lib.rs b/third_party/move/move-compiler-v2/src/lib.rs index 08d687490a80d..87a8bab66fe30 100644 --- a/third_party/move/move-compiler-v2/src/lib.rs +++ b/third_party/move/move-compiler-v2/src/lib.rs @@ -228,6 +228,7 @@ pub fn run_checker(options: Options) -> anyhow::Result { &options.known_attributes }, options.language_version.unwrap_or_default(), + options.compile_test_code, )?; // Store address aliases let map = addrs diff --git a/third_party/move/move-compiler-v2/src/options.rs b/third_party/move/move-compiler-v2/src/options.rs index 6ea10c5f4f57d..4259c9aa491c6 100644 --- a/third_party/move/move-compiler-v2/src/options.rs +++ b/third_party/move/move-compiler-v2/src/options.rs @@ -68,6 +68,9 @@ pub struct Options { /// Whether to compile everything, including dependencies. #[clap(long)] pub whole_program: bool, + /// Whether to compile #[test] and #[test_only] code + #[clap(skip)] + pub compile_test_code: bool, } impl Default for Options { @@ -142,6 +145,20 @@ impl Options { panic!("unknown experiment `{}`", name) } } + + pub fn set_skip_attribute_checks(self, value: bool) -> Self { + Self { + skip_attribute_checks: value, + ..self + } + } + + pub fn set_compile_test_code(self, value: bool) -> Self { + Self { + compile_test_code: value, + ..self + } + } } /// Finds the experiment in the list of definitions. A definition diff --git a/third_party/move/move-compiler-v2/tests/checking/attributes/aptos_stdlib_attributes.exp b/third_party/move/move-compiler-v2/tests/checking/attributes/aptos_stdlib_attributes.exp new file mode 100644 index 0000000000000..3446a4d91b101 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/attributes/aptos_stdlib_attributes.exp @@ -0,0 +1,49 @@ + +Diagnostics: +warning: unknown attribute + ┌─ tests/checking/attributes/aptos_stdlib_attributes.move:4:7 + │ +4 │ #[a, a(x = 0)] + │ ^ Attribute name 'a' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +warning: unknown attribute + ┌─ tests/checking/attributes/aptos_stdlib_attributes.move:4:10 + │ +4 │ #[a, a(x = 0)] + │ ^ Attribute name 'a' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +error: duplicate declaration, item, or annotation + ┌─ tests/checking/attributes/aptos_stdlib_attributes.move:4:10 + │ +4 │ #[a, a(x = 0)] + │ - ^^^^^^^^ Duplicate attribute 'a' attached to the same item + │ │ + │ Attribute previously given here + +warning: unknown attribute + ┌─ tests/checking/attributes/aptos_stdlib_attributes.move:7:7 + │ +7 │ #[testonly] + │ ^^^^^^^^ Attribute name 'testonly' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +warning: unknown attribute + ┌─ tests/checking/attributes/aptos_stdlib_attributes.move:8:7 + │ +8 │ #[b(a, a = 0, a(x = 1))] + │ ^ Attribute name 'b' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +error: duplicate declaration, item, or annotation + ┌─ tests/checking/attributes/aptos_stdlib_attributes.move:8:12 + │ +8 │ #[b(a, a = 0, a(x = 1))] + │ - ^^^^^ Duplicate attribute 'a' attached to the same item + │ │ + │ Attribute previously given here + +error: duplicate declaration, item, or annotation + ┌─ tests/checking/attributes/aptos_stdlib_attributes.move:8:19 + │ +8 │ #[b(a, a = 0, a(x = 1))] + │ - ^^^^^^^^ Duplicate attribute 'a' attached to the same item + │ │ + │ Attribute previously given here diff --git a/third_party/move/move-compiler-v2/tests/checking/attributes/aptos_stdlib_attributes.move b/third_party/move/move-compiler-v2/tests/checking/attributes/aptos_stdlib_attributes.move new file mode 100644 index 0000000000000..a0746a4d37bb9 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/attributes/aptos_stdlib_attributes.move @@ -0,0 +1,10 @@ +// Test that warnings about unknown "#[testonly]" attribute is +// suppressed in aptos_std module. +module aptos_std::module_with_suppressed_warnings { + #[a, a(x = 0)] + fun foo() {} + + #[testonly] + #[b(a, a = 0, a(x = 1))] + fun bar() {} +} diff --git a/third_party/move/move-compiler-v2/tests/checking/attributes/aptos_stdlib_attributes2.exp b/third_party/move/move-compiler-v2/tests/checking/attributes/aptos_stdlib_attributes2.exp new file mode 100644 index 0000000000000..29a8cf8fe1ec4 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/attributes/aptos_stdlib_attributes2.exp @@ -0,0 +1,17 @@ + +Diagnostics: +warning: unknown attribute + ┌─ tests/checking/attributes/aptos_stdlib_attributes2.move:4:7 + │ +4 │ #[testonly] + │ ^^^^^^^^ Attribute name 'testonly' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +// -- Model dump before bytecode pipeline +module 0x1::M { + private fun bar() { + Tuple() + } + private fun foo() { + Tuple() + } +} // end 0x1::M diff --git a/third_party/move/move-compiler-v2/tests/checking/attributes/aptos_stdlib_attributes2.move b/third_party/move/move-compiler-v2/tests/checking/attributes/aptos_stdlib_attributes2.move new file mode 100644 index 0000000000000..781e7484cc8cb --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/attributes/aptos_stdlib_attributes2.move @@ -0,0 +1,6 @@ +module aptos_std::M { + fun foo() {} + + #[testonly] + fun bar() {} +} diff --git a/third_party/move/move-compiler-v2/tests/checking/attributes/attribute_no_closing_bracket.exp b/third_party/move/move-compiler-v2/tests/checking/attributes/attribute_no_closing_bracket.exp new file mode 100644 index 0000000000000..6ad8c820ab384 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/attributes/attribute_no_closing_bracket.exp @@ -0,0 +1,9 @@ + +Diagnostics: +error: unexpected token + ┌─ tests/checking/attributes/attribute_no_closing_bracket.move:4:5 + │ +3 │ #[attr = 0 + │ - To match this '[' +4 │ fun foo() {} + │ ^ Expected ']' diff --git a/third_party/move/move-compiler-v2/tests/checking/attributes/attribute_no_closing_bracket.move b/third_party/move/move-compiler-v2/tests/checking/attributes/attribute_no_closing_bracket.move new file mode 100644 index 0000000000000..9a28c27c391e4 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/attributes/attribute_no_closing_bracket.move @@ -0,0 +1,5 @@ +module 0x42::M { + // Errors expecting a ']' + #[attr = 0 + fun foo() {} +} diff --git a/third_party/move/move-compiler-v2/tests/checking/attributes/attribute_num_sign_no_bracket.exp b/third_party/move/move-compiler-v2/tests/checking/attributes/attribute_num_sign_no_bracket.exp new file mode 100644 index 0000000000000..91cb71c4739f5 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/attributes/attribute_num_sign_no_bracket.exp @@ -0,0 +1,10 @@ + +Diagnostics: +error: unexpected token + ┌─ tests/checking/attributes/attribute_num_sign_no_bracket.move:4:5 + │ +4 │ fun foo() {} + │ ^^^ + │ │ + │ Unexpected 'fun' + │ Expected '[' diff --git a/third_party/move/move-compiler-v2/tests/checking/attributes/attribute_num_sign_no_bracket.move b/third_party/move/move-compiler-v2/tests/checking/attributes/attribute_num_sign_no_bracket.move new file mode 100644 index 0000000000000..467110986958c --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/attributes/attribute_num_sign_no_bracket.move @@ -0,0 +1,5 @@ +module 0x42::M { + // Errors expecting a '[' + # + fun foo() {} +} diff --git a/third_party/move/move-compiler-v2/tests/checking/attributes/attribute_placement.exp b/third_party/move/move-compiler-v2/tests/checking/attributes/attribute_placement.exp new file mode 100644 index 0000000000000..cf5dce82143a6 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/attributes/attribute_placement.exp @@ -0,0 +1,108 @@ + +Diagnostics: +warning: unknown attribute + ┌─ tests/checking/attributes/attribute_placement.move:3:3 + │ +3 │ #[attr] + │ ^^^^ Attribute name 'attr' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +warning: unknown attribute + ┌─ tests/checking/attributes/attribute_placement.move:5:7 + │ +5 │ #[attr] + │ ^^^^ Attribute name 'attr' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +warning: unknown attribute + ┌─ tests/checking/attributes/attribute_placement.move:8:7 + │ +8 │ #[attr] + │ ^^^^ Attribute name 'attr' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +warning: unknown attribute + ┌─ tests/checking/attributes/attribute_placement.move:11:7 + │ +11 │ #[attr] + │ ^^^^ Attribute name 'attr' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +warning: unknown attribute + ┌─ tests/checking/attributes/attribute_placement.move:14:7 + │ +14 │ #[attr] + │ ^^^^ Attribute name 'attr' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +warning: unknown attribute + ┌─ tests/checking/attributes/attribute_placement.move:17:7 + │ +17 │ #[attr] + │ ^^^^ Attribute name 'attr' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +warning: unknown attribute + ┌─ tests/checking/attributes/attribute_placement.move:22:3 + │ +22 │ #[attr] + │ ^^^^ Attribute name 'attr' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +warning: unknown attribute + ┌─ tests/checking/attributes/attribute_placement.move:24:7 + │ +24 │ #[attr] + │ ^^^^ Attribute name 'attr' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +warning: unknown attribute + ┌─ tests/checking/attributes/attribute_placement.move:27:7 + │ +27 │ #[attr] + │ ^^^^ Attribute name 'attr' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +warning: unknown attribute + ┌─ tests/checking/attributes/attribute_placement.move:31:3 + │ +31 │ #[attr] + │ ^^^^ Attribute name 'attr' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +warning: unknown attribute + ┌─ tests/checking/attributes/attribute_placement.move:33:7 + │ +33 │ #[attr] + │ ^^^^ Attribute name 'attr' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +warning: unknown attribute + ┌─ tests/checking/attributes/attribute_placement.move:36:7 + │ +36 │ #[attr] + │ ^^^^ Attribute name 'attr' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +warning: unknown attribute + ┌─ tests/checking/attributes/attribute_placement.move:39:7 + │ +39 │ #[attr] + │ ^^^^ Attribute name 'attr' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +warning: unknown attribute + ┌─ tests/checking/attributes/attribute_placement.move:44:7 + │ +44 │ #[attr] + │ ^^^^ Attribute name 'attr' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +// -- Model dump before bytecode pipeline +module 0x42::N { + public fun bar() { + Tuple() + } +} // end 0x42::N +module 0x42::M { + use 0x42::N; // resolved as: 0x42::N + struct S { + dummy_field: bool, + } + public fun foo() { + N::bar() + } +} // end 0x42::M +module _0 { + use 0x42::M; // resolved as: 0x42::M + private fun main() { + M::foo(); + Tuple() + } +} // end _0 diff --git a/third_party/move/move-compiler-v2/tests/checking/attributes/attribute_placement.move b/third_party/move/move-compiler-v2/tests/checking/attributes/attribute_placement.move new file mode 100644 index 0000000000000..0c50c6f7a5485 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/attributes/attribute_placement.move @@ -0,0 +1,46 @@ +#[attr] +address 0x42 { +#[attr] +module M { + #[attr] + use 0x42::N; + + #[attr] + struct S {} + + #[attr] + const C: u64 = 0; + + #[attr] + public fun foo() { N::bar() } + + #[attr] + spec foo {} +} +} + +#[attr] +module 0x42::N { + #[attr] + friend 0x42::M; + + #[attr] + public fun bar() {} +} + +#[attr] +script { + #[attr] + use 0x42::M; + + #[attr] + const C: u64 = 0; + + #[attr] + fun main() { + M::foo(); + } + + #[attr] + spec main { } +} diff --git a/third_party/move/move-compiler-v2/tests/checking/attributes/attribute_variants.exp b/third_party/move/move-compiler-v2/tests/checking/attributes/attribute_variants.exp new file mode 100644 index 0000000000000..d5d869b25a0f5 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/attributes/attribute_variants.exp @@ -0,0 +1,65 @@ + +Diagnostics: +warning: unknown attribute + ┌─ tests/checking/attributes/attribute_variants.move:2:3 + │ +2 │ #[attr0] + │ ^^^^^ Attribute name 'attr0' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +warning: unknown attribute + ┌─ tests/checking/attributes/attribute_variants.move:3:3 + │ +3 │ #[attr1=0, attr2=b"hello", attr3=x"0f", attr4=0x42, attr5(attr0, attr1, attr2(attr0, attr1=0))] + │ ^^^^^ Attribute name 'attr1' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +warning: unknown attribute + ┌─ tests/checking/attributes/attribute_variants.move:3:12 + │ +3 │ #[attr1=0, attr2=b"hello", attr3=x"0f", attr4=0x42, attr5(attr0, attr1, attr2(attr0, attr1=0))] + │ ^^^^^ Attribute name 'attr2' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +warning: unknown attribute + ┌─ tests/checking/attributes/attribute_variants.move:3:28 + │ +3 │ #[attr1=0, attr2=b"hello", attr3=x"0f", attr4=0x42, attr5(attr0, attr1, attr2(attr0, attr1=0))] + │ ^^^^^ Attribute name 'attr3' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +warning: unknown attribute + ┌─ tests/checking/attributes/attribute_variants.move:3:41 + │ +3 │ #[attr1=0, attr2=b"hello", attr3=x"0f", attr4=0x42, attr5(attr0, attr1, attr2(attr0, attr1=0))] + │ ^^^^^ Attribute name 'attr4' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +warning: unknown attribute + ┌─ tests/checking/attributes/attribute_variants.move:3:53 + │ +3 │ #[attr1=0, attr2=b"hello", attr3=x"0f", attr4=0x42, attr5(attr0, attr1, attr2(attr0, attr1=0))] + │ ^^^^^ Attribute name 'attr5' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +warning: unknown attribute + ┌─ tests/checking/attributes/attribute_variants.move:4:3 + │ +4 │ #[bttr0=false, bttr1=0u8, bttr2=0u64, bttr3=0u128] + │ ^^^^^ Attribute name 'bttr0' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +warning: unknown attribute + ┌─ tests/checking/attributes/attribute_variants.move:4:16 + │ +4 │ #[bttr0=false, bttr1=0u8, bttr2=0u64, bttr3=0u128] + │ ^^^^^ Attribute name 'bttr1' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +warning: unknown attribute + ┌─ tests/checking/attributes/attribute_variants.move:4:27 + │ +4 │ #[bttr0=false, bttr1=0u8, bttr2=0u64, bttr3=0u128] + │ ^^^^^ Attribute name 'bttr2' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +warning: unknown attribute + ┌─ tests/checking/attributes/attribute_variants.move:4:39 + │ +4 │ #[bttr0=false, bttr1=0u8, bttr2=0u64, bttr3=0u128] + │ ^^^^^ Attribute name 'bttr3' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +// -- Model dump before bytecode pipeline +module 0x42::M { +} // end 0x42::M diff --git a/third_party/move/move-compiler-v2/tests/checking/attributes/attribute_variants.move b/third_party/move/move-compiler-v2/tests/checking/attributes/attribute_variants.move new file mode 100644 index 0000000000000..482fa4cbacacc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/attributes/attribute_variants.move @@ -0,0 +1,6 @@ +#[] +#[attr0] +#[attr1=0, attr2=b"hello", attr3=x"0f", attr4=0x42, attr5(attr0, attr1, attr2(attr0, attr1=0))] +#[bttr0=false, bttr1=0u8, bttr2=0u64, bttr3=0u128] +#[] +module 0x42::M {} diff --git a/third_party/move/move-compiler-v2/tests/checking/attributes/duplicate_attributes.exp b/third_party/move/move-compiler-v2/tests/checking/attributes/duplicate_attributes.exp new file mode 100644 index 0000000000000..6b0c02b1d1b73 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/attributes/duplicate_attributes.exp @@ -0,0 +1,43 @@ + +Diagnostics: +warning: unknown attribute + ┌─ tests/checking/attributes/duplicate_attributes.move:2:7 + │ +2 │ #[a, a(x = 0)] + │ ^ Attribute name 'a' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +warning: unknown attribute + ┌─ tests/checking/attributes/duplicate_attributes.move:2:10 + │ +2 │ #[a, a(x = 0)] + │ ^ Attribute name 'a' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +error: duplicate declaration, item, or annotation + ┌─ tests/checking/attributes/duplicate_attributes.move:2:10 + │ +2 │ #[a, a(x = 0)] + │ - ^^^^^^^^ Duplicate attribute 'a' attached to the same item + │ │ + │ Attribute previously given here + +warning: unknown attribute + ┌─ tests/checking/attributes/duplicate_attributes.move:5:7 + │ +5 │ #[b(a, a = 0, a(x = 1))] + │ ^ Attribute name 'b' is unknown (use --skip-attribute-checks CLI option to ignore); known attributes are '{"bytecode_instruction", "deprecated", "expected_failure", "native_interface", "test", "test_only", "verify_only"}'. + +error: duplicate declaration, item, or annotation + ┌─ tests/checking/attributes/duplicate_attributes.move:5:12 + │ +5 │ #[b(a, a = 0, a(x = 1))] + │ - ^^^^^ Duplicate attribute 'a' attached to the same item + │ │ + │ Attribute previously given here + +error: duplicate declaration, item, or annotation + ┌─ tests/checking/attributes/duplicate_attributes.move:5:19 + │ +5 │ #[b(a, a = 0, a(x = 1))] + │ - ^^^^^^^^ Duplicate attribute 'a' attached to the same item + │ │ + │ Attribute previously given here diff --git a/third_party/move/move-compiler-v2/tests/checking/attributes/duplicate_attributes.move b/third_party/move/move-compiler-v2/tests/checking/attributes/duplicate_attributes.move new file mode 100644 index 0000000000000..e2de77f0f23a4 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/attributes/duplicate_attributes.move @@ -0,0 +1,7 @@ +module 0x42::M { + #[a, a(x = 0)] + fun foo() {} + + #[b(a, a = 0, a(x = 1))] + fun bar() {} +} diff --git a/third_party/move/move-compiler-v2/tests/skip_attribute_checks/aptos_stdlib_attributes.exp b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/aptos_stdlib_attributes.exp new file mode 100644 index 0000000000000..d48084aad10e5 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/aptos_stdlib_attributes.exp @@ -0,0 +1,25 @@ + +Diagnostics: +error: duplicate declaration, item, or annotation + ┌─ tests/skip_attribute_checks/aptos_stdlib_attributes.move:4:10 + │ +4 │ #[a, a(x = 0)] + │ - ^^^^^^^^ Duplicate attribute 'a' attached to the same item + │ │ + │ Attribute previously given here + +error: duplicate declaration, item, or annotation + ┌─ tests/skip_attribute_checks/aptos_stdlib_attributes.move:8:12 + │ +8 │ #[b(a, a = 0, a(x = 1))] + │ - ^^^^^ Duplicate attribute 'a' attached to the same item + │ │ + │ Attribute previously given here + +error: duplicate declaration, item, or annotation + ┌─ tests/skip_attribute_checks/aptos_stdlib_attributes.move:8:19 + │ +8 │ #[b(a, a = 0, a(x = 1))] + │ - ^^^^^^^^ Duplicate attribute 'a' attached to the same item + │ │ + │ Attribute previously given here diff --git a/third_party/move/move-compiler-v2/tests/skip_attribute_checks/aptos_stdlib_attributes.move b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/aptos_stdlib_attributes.move new file mode 100644 index 0000000000000..a0746a4d37bb9 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/aptos_stdlib_attributes.move @@ -0,0 +1,10 @@ +// Test that warnings about unknown "#[testonly]" attribute is +// suppressed in aptos_std module. +module aptos_std::module_with_suppressed_warnings { + #[a, a(x = 0)] + fun foo() {} + + #[testonly] + #[b(a, a = 0, a(x = 1))] + fun bar() {} +} diff --git a/third_party/move/move-compiler-v2/tests/skip_attribute_checks/aptos_stdlib_attributes2.move b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/aptos_stdlib_attributes2.move new file mode 100644 index 0000000000000..781e7484cc8cb --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/aptos_stdlib_attributes2.move @@ -0,0 +1,6 @@ +module aptos_std::M { + fun foo() {} + + #[testonly] + fun bar() {} +} diff --git a/third_party/move/move-compiler-v2/tests/skip_attribute_checks/attribute_no_closing_bracket.exp b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/attribute_no_closing_bracket.exp new file mode 100644 index 0000000000000..ce1ddf47797bd --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/attribute_no_closing_bracket.exp @@ -0,0 +1,9 @@ + +Diagnostics: +error: unexpected token + ┌─ tests/skip_attribute_checks/attribute_no_closing_bracket.move:4:5 + │ +3 │ #[attr = 0 + │ - To match this '[' +4 │ fun foo() {} + │ ^ Expected ']' diff --git a/third_party/move/move-compiler-v2/tests/skip_attribute_checks/attribute_no_closing_bracket.move b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/attribute_no_closing_bracket.move new file mode 100644 index 0000000000000..9a28c27c391e4 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/attribute_no_closing_bracket.move @@ -0,0 +1,5 @@ +module 0x42::M { + // Errors expecting a ']' + #[attr = 0 + fun foo() {} +} diff --git a/third_party/move/move-compiler-v2/tests/skip_attribute_checks/attribute_placement.move b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/attribute_placement.move new file mode 100644 index 0000000000000..0c50c6f7a5485 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/attribute_placement.move @@ -0,0 +1,46 @@ +#[attr] +address 0x42 { +#[attr] +module M { + #[attr] + use 0x42::N; + + #[attr] + struct S {} + + #[attr] + const C: u64 = 0; + + #[attr] + public fun foo() { N::bar() } + + #[attr] + spec foo {} +} +} + +#[attr] +module 0x42::N { + #[attr] + friend 0x42::M; + + #[attr] + public fun bar() {} +} + +#[attr] +script { + #[attr] + use 0x42::M; + + #[attr] + const C: u64 = 0; + + #[attr] + fun main() { + M::foo(); + } + + #[attr] + spec main { } +} diff --git a/third_party/move/move-compiler-v2/tests/skip_attribute_checks/attribute_variants.move b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/attribute_variants.move new file mode 100644 index 0000000000000..482fa4cbacacc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/attribute_variants.move @@ -0,0 +1,6 @@ +#[] +#[attr0] +#[attr1=0, attr2=b"hello", attr3=x"0f", attr4=0x42, attr5(attr0, attr1, attr2(attr0, attr1=0))] +#[bttr0=false, bttr1=0u8, bttr2=0u64, bttr3=0u128] +#[] +module 0x42::M {} diff --git a/third_party/move/move-compiler-v2/tests/skip_attribute_checks/duplicate_attributes.exp b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/duplicate_attributes.exp new file mode 100644 index 0000000000000..5623b42c8d9e3 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/duplicate_attributes.exp @@ -0,0 +1,25 @@ + +Diagnostics: +error: duplicate declaration, item, or annotation + ┌─ tests/skip_attribute_checks/duplicate_attributes.move:2:10 + │ +2 │ #[a, a(x = 0)] + │ - ^^^^^^^^ Duplicate attribute 'a' attached to the same item + │ │ + │ Attribute previously given here + +error: duplicate declaration, item, or annotation + ┌─ tests/skip_attribute_checks/duplicate_attributes.move:5:12 + │ +5 │ #[b(a, a = 0, a(x = 1))] + │ - ^^^^^ Duplicate attribute 'a' attached to the same item + │ │ + │ Attribute previously given here + +error: duplicate declaration, item, or annotation + ┌─ tests/skip_attribute_checks/duplicate_attributes.move:5:19 + │ +5 │ #[b(a, a = 0, a(x = 1))] + │ - ^^^^^^^^ Duplicate attribute 'a' attached to the same item + │ │ + │ Attribute previously given here diff --git a/third_party/move/move-compiler-v2/tests/skip_attribute_checks/duplicate_attributes.move b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/duplicate_attributes.move new file mode 100644 index 0000000000000..e2de77f0f23a4 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/duplicate_attributes.move @@ -0,0 +1,7 @@ +module 0x42::M { + #[a, a(x = 0)] + fun foo() {} + + #[b(a, a = 0, a(x = 1))] + fun bar() {} +} diff --git a/third_party/move/move-compiler-v2/tests/skip_attribute_checks/extra_attributes.move b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/extra_attributes.move new file mode 100644 index 0000000000000..11ff5533c4f37 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/extra_attributes.move @@ -0,0 +1,26 @@ +// tests non-abort related execution failures +module 0x1::n {} +module 0x1::m { + #[test_only] + use 0x1::n; + + #[test] + #[expected_failure(vector_error, location=std::vector, hello=0)] + fun t0() { } + + #[test] + #[expected_failure(arithmetic_error, location=n, wowza)] + fun t1() { } + + #[test] + #[expected_failure(out_of_gas, location=Self, so_many_attrs)] + fun t2() { } + + #[test] + #[expected_failure(major_status=4004, an_attr_here_is_unused, location=Self)] + fun t3() { } + + #[test] + #[expected_failure(major_status=4016, minor_code=0, location=Self)] + fun t4() { } +} diff --git a/third_party/move/move-compiler-v2/tests/skip_attribute_checks/extra_attributes2.move b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/extra_attributes2.move new file mode 100644 index 0000000000000..ba09afd866987 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/extra_attributes2.move @@ -0,0 +1,23 @@ +// tests non-abort related execution failures with errors in attributes +module 0x1::n {} +module 0x1::m { + #[test] + #[expected_failure(arithmetic_error, location=Self)] + fun t5() { } + + #[test] + #[expected_failure(abort_code=3, test, location=Self)] + fun t6() { } + + #[test] + #[expected_failure(vector_error, test_only, location=Self)] + fun t7() { } + + #[test_only] + #[expected_failure(bytecode_instruction, location=Self)] + fun t8() { } + + #[test] + #[expected_failure(verify_only)] + fun t9() { } +} diff --git a/third_party/move/move-compiler-v2/tests/skip_attribute_checks/testonly.move b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/testonly.move new file mode 100644 index 0000000000000..0923625d717ba --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/testonly.move @@ -0,0 +1,9 @@ +module 0x1::A { + #[test] + fun a() { } + + #[testonly] + public fun a_call() { + abort 0 + } +} diff --git a/third_party/move/move-compiler-v2/tests/testsuite.rs b/third_party/move/move-compiler-v2/tests/testsuite.rs index 55d84c3fdf798..0546fe3098ae0 100644 --- a/third_party/move/move-compiler-v2/tests/testsuite.rs +++ b/third_party/move/move-compiler-v2/tests/testsuite.rs @@ -489,6 +489,52 @@ const TEST_CONFIGS: Lazy> = Lazy::new(|| { dump_bytecode: DumpLevel::EndStage, dump_bytecode_filter: Some(vec![FILE_FORMAT_STAGE]), }, + // Test for unit tests on and off + TestConfig { + name: "unit-test-on", + runner: |p| run_test(p, get_config_by_name("unit-test-on")), + include: vec!["/unit_test/test/"], + exclude: vec![], + exp_suffix: None, + options: opts + .clone() + .set_experiment(Experiment::AST_SIMPLIFY, true) + .set_compile_test_code(true), + stop_after: StopAfter::BytecodePipeline(None), + dump_ast: DumpLevel::None, + dump_bytecode: DumpLevel::None, + dump_bytecode_filter: None, + }, + TestConfig { + name: "unit-test-off", + runner: |p| run_test(p, get_config_by_name("unit-test-off")), + include: vec!["/unit_test/notest/"], + exclude: vec![], + exp_suffix: None, + options: opts + .clone() + .set_experiment(Experiment::AST_SIMPLIFY, true) + .set_compile_test_code(false), + stop_after: StopAfter::BytecodePipeline(None), + dump_ast: DumpLevel::None, + dump_bytecode: DumpLevel::None, + dump_bytecode_filter: None, + }, + TestConfig { + name: "skip-attribute-checks", + runner: |p| run_test(p, get_config_by_name("skip-attribute-checks")), + include: vec!["/skip_attribute_checks/"], + exclude: vec![], + exp_suffix: None, + options: opts + .clone() + .set_experiment(Experiment::AST_SIMPLIFY, true) + .set_skip_attribute_checks(true), + stop_after: StopAfter::BytecodePipeline(None), + dump_ast: DumpLevel::None, + dump_bytecode: DumpLevel::None, + dump_bytecode_filter: None, + }, ]; configs.into_iter().map(|c| (c.name, c)).collect() }); @@ -515,7 +561,15 @@ fn run_test(path: &Path, config: TestConfig) -> datatest_stable::Result<()> { } else { vec![] }; - options.named_address_mapping = vec!["std=0x1".to_string()]; + options.named_address_mapping = vec![ + "std=0x1".to_string(), + "aptos_std=0x1".to_string(), + "M=0x1".to_string(), + "A=0x42".to_string(), + "B=0x42".to_string(), + "K=0x19".to_string(), + "Async=0x20".to_string(), + ]; // Putting the generated test baseline into a Refcell to avoid problems with mut borrow // in closures. diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/attribute_location.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/attribute_location.move new file mode 100644 index 0000000000000..2ece812bb8ac1 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/attribute_location.move @@ -0,0 +1,33 @@ +#[test_only] +address 0x42 { +module A { + struct T {} +} +} + +#[test_only] +module 0x42::M { +} + +module 0x42::N { + #[test_only] + friend 0x42::M; + + #[test_only] + use 0x42::A; + + #[test_only] + const C: u64 = 0; + + #[test_only] + struct S { f: A::T } + + #[test_only] + fun foo() {} +} + +module 0x42::Z { + #[test] + #[expected_failure(abort_code = 0, location = 0x42::Z )] + fun foo() { abort 0 } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/attribute_location_invalid.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/attribute_location_invalid.exp new file mode 100644 index 0000000000000..604edffd131f2 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/attribute_location_invalid.exp @@ -0,0 +1,16 @@ + +Diagnostics: +error: unable to generate test + ┌─ tests/unit_test/notest/attribute_location_invalid.move:1:3 + │ +1 │ #[test_only] + │ ^^^^^^^^^ Testing attributes are not allowed in scripts. + +error: invalid attribute + ┌─ tests/unit_test/notest/attribute_location_invalid.move:10:7 + │ +10 │ #[expected_failure(abort_code = 0)] + │ ^^^^^^^^^^^^^^^^ + │ │ + │ Attribute 'expected_failure' is not expected with a struct + │ Expected to be used with one of the following: function diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/attribute_location_invalid.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/attribute_location_invalid.move new file mode 100644 index 0000000000000..e87b8b22b27ed --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/attribute_location_invalid.move @@ -0,0 +1,12 @@ +#[test_only] +script { + fun main() {} +} + +#[test] +module 0x42::M {} + +module 0x42::N { + #[expected_failure(abort_code = 0)] + struct S {} +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/cross_module_members.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/cross_module_members.move new file mode 100644 index 0000000000000..40b60250e6b5e --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/cross_module_members.move @@ -0,0 +1,24 @@ +// Check that test_only filtering and calling is supported across modules and +// different types of module members +address 0x1 { +module A { + #[test_only] + struct Foo has drop {} + + #[test_only] + public fun build_foo(): Foo { Foo {} } +} + +module B { + #[test_only] + use 0x1::A::{Self, Foo}; + + #[test_only] + fun x(_: Foo) { } + + #[test] + fun tester() { + x(A::build_foo()) + } +} +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/cross_module_members_non_test_function.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/cross_module_members_non_test_function.exp new file mode 100644 index 0000000000000..c0e6aba44b631 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/cross_module_members_non_test_function.exp @@ -0,0 +1,7 @@ + +Diagnostics: +error: unbound module + ┌─ tests/unit_test/notest/cross_module_members_non_test_function.move:24:9 + │ +24 │ A::build_foo() + │ ^ Unbound module alias 'A' diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/cross_module_members_non_test_function.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/cross_module_members_non_test_function.move new file mode 100644 index 0000000000000..1cb0df8ff9f9a --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/cross_module_members_non_test_function.move @@ -0,0 +1,27 @@ +// check that `use`'s are filtered out correctly in non-test mode +address 0x1 { +module A { + struct Foo has drop {} + + public fun build_foo(): Foo { Foo {} } +} + +module B { + #[test_only] + use 0x1::A::{Self, Foo}; + + #[test_only] + fun x(_: Foo) { } + + #[test] + fun tester() { + x(A::build_foo()) + } + + // this should fail find the A module in non-test mode as the use statement + // for `A` is test_only. + public fun bad(): Foo { + A::build_foo() + } +} +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/cross_module_test_only_module.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/cross_module_test_only_module.exp new file mode 100644 index 0000000000000..9921e6e56d93d --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/cross_module_test_only_module.exp @@ -0,0 +1,13 @@ + +Diagnostics: +error: unbound module + ┌─ tests/unit_test/notest/cross_module_test_only_module.move:10:9 + │ +10 │ use 0x1::M; + │ ^^^^^^ Invalid 'use'. Unbound module: '0x1::M' + +error: unbound module + ┌─ tests/unit_test/notest/cross_module_test_only_module.move:13:9 + │ +13 │ M::foo() + │ ^ Unbound module alias 'M' diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/cross_module_test_only_module.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/cross_module_test_only_module.move new file mode 100644 index 0000000000000..90bf3320c6b8f --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/cross_module_test_only_module.move @@ -0,0 +1,16 @@ +// check that modules that are annotated as test_only are filtered out correctly +address 0x1 { +#[test_only] +module M { + public fun foo() { } +} + +module Tests { + // this use should cause an unbound module error as M should be filtered out + use 0x1::M; + + fun bar() { + M::foo() + } +} +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_bad_value.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_bad_value.move new file mode 100644 index 0000000000000..bc113722c826e --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_bad_value.move @@ -0,0 +1,25 @@ +// check that invalid abort_code values cannot be assigned +module 0x1::A { + #[test_only] + struct Foo has drop {} + + #[test] + #[expected_failure(abort_code=true)] + fun assign_boolean_abort_code() { } + + #[test] + #[expected_failure(abort_code=x"")] + fun assign_hexbyte_abort_code() { } + + #[test] + #[expected_failure(abort_code=b"")] + fun assign_byte_abort_code() { } + + #[test] + #[expected_failure(abort_code=Foo)] + fun assign_struct_abort_code() { } + + #[test] + #[expected_failure(abort_code=@0xC0FFEE)] + fun assign_address_abort_code() { } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_constants.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_constants.move new file mode 100644 index 0000000000000..3ecbcdeddb24d --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_constants.move @@ -0,0 +1,33 @@ +module 0x2::m { + const C: u64 = 0 + 1 + 2; +} + +// check that constants can be used +module 0x1::A { + #[test_only] + use 0x2::m as x; + + const C0: u64 = 0; + #[test_only] + const C1: u64 = 0; + + #[test] + #[expected_failure(abort_code=C0)] + fun use_c0() { } + + #[test] + #[expected_failure(abort_code=C1)] + fun use_c1() { } + + #[test] + #[expected_failure(abort_code=x::C)] + fun use_through_alias() { } + + #[test] + #[expected_failure(abort_code=0x1::A::C0)] + fun use_explicit_internal() { } + + #[test] + #[expected_failure(abort_code=0x2::m::C)] + fun use_explicit_external() { } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_constants_invalid.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_constants_invalid.move new file mode 100644 index 0000000000000..60c3aac5227c8 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_constants_invalid.move @@ -0,0 +1,19 @@ +module 0x2::m { + const C: u8 = 0 + 1 + 2; +} + +// check invalid constant usage +module 0x1::A { + + #[test] + #[expected_failure(abort_code=0x2::m::C)] + fun not_u64() { } + + #[test] + #[expected_failure(abort_code=0x2::x::C)] + fun unbound_module() { } + + #[test] + #[expected_failure(abort_code=0x1::A::C0)] + fun unbound_constant() { } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_invalid_literals.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_invalid_literals.move new file mode 100644 index 0000000000000..511dd24586332 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_invalid_literals.move @@ -0,0 +1,21 @@ +// check that only non-annotated integer literals and u64s can be assigned to +// abort codes +address 0x1 { +module M { + #[test] + #[expected_failure(abort_code=0, location=0x1::M)] + fun ok1() { } + + #[test] + #[expected_failure(abort_code=0u64, location=0x1::M)] + fun ok2() { } + + #[test] + #[expected_failure(abort_code=0u8, location=0x1::M)] + fun fail_annot1() { } + + #[test] + #[expected_failure(abort_code=0u128, location=0x1::M)] + fun fail_annot3() { } +} +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_not_test.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_not_test.move new file mode 100644 index 0000000000000..dc0a6a618bde7 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_not_test.move @@ -0,0 +1,8 @@ +// expected_failure attributes can only be placed on #[test] functions +module 0x1::A { + #[expected_failure] + fun foo() { } + + #[test_only, expected_failure] + fun bar() { } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_on_non_function.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_on_non_function.exp new file mode 100644 index 0000000000000..9ded60b3c63de --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_on_non_function.exp @@ -0,0 +1,28 @@ + +Diagnostics: +error: invalid attribute + ┌─ tests/unit_test/notest/expected_failure_on_non_function.move:3:7 + │ +3 │ #[expected_failure] + │ ^^^^^^^^^^^^^^^^ + │ │ + │ Attribute 'expected_failure' is not expected with a struct + │ Expected to be used with one of the following: function + +error: invalid attribute + ┌─ tests/unit_test/notest/expected_failure_on_non_function.move:6:7 + │ +6 │ #[expected_failure] + │ ^^^^^^^^^^^^^^^^ + │ │ + │ Attribute 'expected_failure' is not expected with a use + │ Expected to be used with one of the following: function + +error: invalid attribute + ┌─ tests/unit_test/notest/expected_failure_on_non_function.move:9:7 + │ +9 │ #[expected_failure] + │ ^^^^^^^^^^^^^^^^ + │ │ + │ Attribute 'expected_failure' is not expected with a constant + │ Expected to be used with one of the following: function diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_on_non_function.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_on_non_function.move new file mode 100644 index 0000000000000..94822f1b4b21d --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_on_non_function.move @@ -0,0 +1,13 @@ +// expected_failure attributes can only be placed on #[test] functions +module 0x1::A { + #[expected_failure] + struct Foo {} + + #[expected_failure] + use 0x1::A; + + #[expected_failure] + const C: u64 = 0; + + struct Bar { f: A::Foo } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_out_of_range_value.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_out_of_range_value.move new file mode 100644 index 0000000000000..1564dee73fbca --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_out_of_range_value.move @@ -0,0 +1,19 @@ +// abort_code numbers need to remain in the u64 range +address 0x1 { +module M { + // at u64::max - 1, OK + #[test] + #[expected_failure(abort_code=18446744073709551614)] + fun ok() { } + + // at u64::max, OK + #[test] + #[expected_failure(abort_code=18446744073709551615)] + fun at_max_ok() { } + + // at u64::max + 1, raise an error + #[test] + #[expected_failure(abort_code=18446744073709551616)] + fun past_max_should_fail() { } +} +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/extra_attributes.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/extra_attributes.move new file mode 100644 index 0000000000000..11ff5533c4f37 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/extra_attributes.move @@ -0,0 +1,26 @@ +// tests non-abort related execution failures +module 0x1::n {} +module 0x1::m { + #[test_only] + use 0x1::n; + + #[test] + #[expected_failure(vector_error, location=std::vector, hello=0)] + fun t0() { } + + #[test] + #[expected_failure(arithmetic_error, location=n, wowza)] + fun t1() { } + + #[test] + #[expected_failure(out_of_gas, location=Self, so_many_attrs)] + fun t2() { } + + #[test] + #[expected_failure(major_status=4004, an_attr_here_is_unused, location=Self)] + fun t3() { } + + #[test] + #[expected_failure(major_status=4016, minor_code=0, location=Self)] + fun t4() { } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/extra_attributes2.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/extra_attributes2.move new file mode 100644 index 0000000000000..ba09afd866987 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/extra_attributes2.move @@ -0,0 +1,23 @@ +// tests non-abort related execution failures with errors in attributes +module 0x1::n {} +module 0x1::m { + #[test] + #[expected_failure(arithmetic_error, location=Self)] + fun t5() { } + + #[test] + #[expected_failure(abort_code=3, test, location=Self)] + fun t6() { } + + #[test] + #[expected_failure(vector_error, test_only, location=Self)] + fun t7() { } + + #[test_only] + #[expected_failure(bytecode_instruction, location=Self)] + fun t8() { } + + #[test] + #[expected_failure(verify_only)] + fun t9() { } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/invalid_expected_code_name.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/invalid_expected_code_name.move new file mode 100644 index 0000000000000..c81a2f6db7dda --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/invalid_expected_code_name.move @@ -0,0 +1,14 @@ +// only "abort_code" can be used as the expected_failure abort code assignment name +module 0x1::M { + #[test] + #[expected_failure(cod=1)] + fun no() {} + + #[test] + #[expected_failure(code=1)] + fun nope() {} + + #[test] + #[expected_failure(abort_cod=1)] + fun noo() {} +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/invalid_expected_failure_name.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/invalid_expected_failure_name.move new file mode 100644 index 0000000000000..8d20123ca9c76 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/invalid_expected_failure_name.move @@ -0,0 +1,6 @@ +// straight assignment of an abort code to the expected_failure attribute isn't allowed +module 0x1::M { + #[test] + #[expected_failure=1] + fun f() { } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/multiple_errors.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/multiple_errors.move new file mode 100644 index 0000000000000..b16f86093c5b9 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/multiple_errors.move @@ -0,0 +1,45 @@ +// test that we handle multiple errors in the same file correctly and don't stop at the first one +address 0x1 { +module M { + #[test_only] + struct Foo {} + + public fun foo() { } + + #[test_only] + public fun bar() { } + + #[test] + public fun go() { } + + #[test(_a=@0x1)] + public fun a(_a: signer) { } + + // failure: invalid value in test parameter assignment + #[test(_a=Foo)] + public fun b(_a: signer) { } + + #[test(_a=@0x1, _b=@0x2)] + public fun c(_a: signer, _b: signer) { } + + // failure: double annotation + #[test(_a=@0x1)] + #[test(_b=@0x2)] + public fun d(_a: signer, _b: signer) { } + + // failure: annotated as both test and test_only + #[test(_a=@0x1)] + #[test_only] + public fun e(_a: signer, _b: signer) { } + + // failure: invalid number of signer arguments + #[test(_a=@0x1)] + public fun f(_a: signer, _b: signer) { } + + // failure: double annotation + #[test(_a=@0x1)] + #[expected_failure] + #[expected_failure] + public fun g(_a: signer, _b: signer) { } +} +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/multiple_test_annotations.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/multiple_test_annotations.move new file mode 100644 index 0000000000000..e5502ad96a084 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/multiple_test_annotations.move @@ -0,0 +1,13 @@ +// cannot have multiple #[test] attributes. Only one test attribute is allowed, +// and all signer arguments need to be assigned in that attribute. +address 0x1 { +module M { + #[test(_a=@0x1)] + #[test(_b=@0x2)] + public fun a(_a: signer, _b: signer) { } + + #[test] + #[test(_a=@0x1, _b=@0x2)] + public fun b(_a: signer, _b: signer) { } +} +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/named_address_no_value_in_annotation.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/named_address_no_value_in_annotation.move new file mode 100644 index 0000000000000..b820da2ddc31b --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/named_address_no_value_in_annotation.move @@ -0,0 +1,4 @@ +module 0x1::M { + #[test(_a = @UnboundAddr)] + fun test(_a: signer) { } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_invalid_assignment.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_invalid_assignment.move new file mode 100644 index 0000000000000..ce614152846e9 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_invalid_assignment.move @@ -0,0 +1,32 @@ +// tests non-abort related execution failures +// invalid assignment +module 0x1::n {} +module 0x1::m { + #[test_only] + use 0x1::n; + + #[test] + #[expected_failure(vector_error=0, location=std::vector)] + fun t0() { } + + #[test] + #[expected_failure(vector_error, minor_status=x"", location=std::vector)] + fun t1() { } + + #[test] + #[expected_failure(arithmetic_error=@0, location=n)] + fun t2() { } + + #[test] + #[expected_failure(out_of_gas=bool, location=Self)] + fun t3() { } + + #[test] + #[expected_failure(major_status=4004u128, location=Self)] + fun t4() { } + + #[test] + #[expected_failure(major_status=4016, minor_status=b"", location=Self)] + fun t5() { } + +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_invalid_location.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_invalid_location.move new file mode 100644 index 0000000000000..786652248169f --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_invalid_location.move @@ -0,0 +1,41 @@ +// tests non-abort related execution failures +// missing or invalid location +module 0x1::m { + + #[test] + #[expected_failure(vector_error)] + fun t0() { } + + #[test] + #[expected_failure(arithmetic_error)] + fun t1() { } + + #[test] + #[expected_failure(out_of_gas)] + fun t2() { } + + #[test] + #[expected_failure(major_status=4004)] + fun t3() { } + + #[test] + #[expected_failure(major_status=4016, minor_code=0)] + fun t4() { } + + #[test] + #[expected_failure(vector_error, location=x)] + fun u0() { } + + #[test] + #[expected_failure(out_of_gas, location=0x1::m::t0)] + fun u2() { } + + #[test] + #[expected_failure(major_status=4004, location=self)] + fun u3() { } + + #[test] + #[expected_failure(major_status=4016, minor_status=0, location=0)] + fun u4() { } + +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_invalid_location_module.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_invalid_location_module.move new file mode 100644 index 0000000000000..7b5cd5a42b89b --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_invalid_location_module.move @@ -0,0 +1,9 @@ +// tests non-abort related execution failures +// invalid module in location +module 0x1::m { + + #[test] + #[expected_failure(arithmetic_error, location=0x2::m)] + fun u1() { } + +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_valid.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_valid.move new file mode 100644 index 0000000000000..c04e9d5c3155e --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_valid.move @@ -0,0 +1,27 @@ +// tests non-abort related execution failures +module 0x1::n {} +module 0x1::m { + #[test_only] + use 0x1::n; + + #[test] + #[expected_failure(vector_error, location=std::vector)] + fun t0() { } + + #[test] + #[expected_failure(arithmetic_error, location=n)] + fun t1() { } + + #[test] + #[expected_failure(out_of_gas, location=Self)] + fun t2() { } + + #[test] + #[expected_failure(major_status=4004, location=Self)] + fun t3() { } + + #[test] + #[expected_failure(major_status=4016, minor_status=0, location=Self)] + fun t4() { } + +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_multiple_on_main.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_multiple_on_main.exp new file mode 100644 index 0000000000000..c3eb797a70c43 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_multiple_on_main.exp @@ -0,0 +1,19 @@ + +Diagnostics: +error: unable to generate test + ┌─ tests/unit_test/notest/script_with_multiple_on_main.move:4:7 + │ +4 │ #[expected_failure] + │ ^^^^^^^^^^^^^^^^ Testing attributes are not allowed in scripts. + +error: unable to generate test + ┌─ tests/unit_test/notest/script_with_multiple_on_main.move:5:7 + │ +5 │ #[test_only, test] + │ ^^^^^^^^^ Testing attributes are not allowed in scripts. + +error: unable to generate test + ┌─ tests/unit_test/notest/script_with_multiple_on_main.move:5:18 + │ +5 │ #[test_only, test] + │ ^^^^ Testing attributes are not allowed in scripts. diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_multiple_on_main.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_multiple_on_main.move new file mode 100644 index 0000000000000..7bd77e2b0d2eb --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_multiple_on_main.move @@ -0,0 +1,7 @@ +// test-related attributes are not allowed in and/or on scripts. We should get an error +// pointing to each one of the attributes in this test. Test annotations inside of a script. +script { + #[expected_failure] + #[test_only, test] + fun main() { } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_multiple_top_level.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_multiple_top_level.exp new file mode 100644 index 0000000000000..4e10978d05ba5 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_multiple_top_level.exp @@ -0,0 +1,19 @@ + +Diagnostics: +error: unable to generate test + ┌─ tests/unit_test/notest/script_with_multiple_top_level.move:3:3 + │ +3 │ #[test, expected_failure] + │ ^^^^ Testing attributes are not allowed in scripts. + +error: unable to generate test + ┌─ tests/unit_test/notest/script_with_multiple_top_level.move:3:9 + │ +3 │ #[test, expected_failure] + │ ^^^^^^^^^^^^^^^^ Testing attributes are not allowed in scripts. + +error: unable to generate test + ┌─ tests/unit_test/notest/script_with_multiple_top_level.move:4:3 + │ +4 │ #[test_only] + │ ^^^^^^^^^ Testing attributes are not allowed in scripts. diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_multiple_top_level.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_multiple_top_level.move new file mode 100644 index 0000000000000..1742f4e6ba2c4 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_multiple_top_level.move @@ -0,0 +1,7 @@ +// test-related attributes are not allowed in and/or on scripts. We should get an error +// pointing to each one of the attributes in this test. Test annotations on a script. +#[test, expected_failure] +#[test_only] +script { + fun main() { } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_test_on_main.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_test_on_main.exp new file mode 100644 index 0000000000000..281a58e0b3a26 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_test_on_main.exp @@ -0,0 +1,7 @@ + +Diagnostics: +error: unable to generate test + ┌─ tests/unit_test/notest/script_with_test_on_main.move:3:7 + │ +3 │ #[test] + │ ^^^^ Testing attributes are not allowed in scripts. diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_test_on_main.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_test_on_main.move new file mode 100644 index 0000000000000..596a98be2f2e1 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_test_on_main.move @@ -0,0 +1,5 @@ +// Test a single annotation inside of a script that isn't allowed. +script { + #[test] + fun main() { } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_test_top_level.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_test_top_level.exp new file mode 100644 index 0000000000000..dde5ff63e347d --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_test_top_level.exp @@ -0,0 +1,7 @@ + +Diagnostics: +error: unable to generate test + ┌─ tests/unit_test/notest/script_with_test_top_level.move:2:3 + │ +2 │ #[test_only] + │ ^^^^^^^^^ Testing attributes are not allowed in scripts. diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_test_top_level.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_test_top_level.move new file mode 100644 index 0000000000000..baa84e7525957 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/script_with_test_top_level.move @@ -0,0 +1,5 @@ +// test a single test-related attribute on a script that isn't allowed +#[test_only] +script { + fun main() { } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/test_and_test_only_annotation.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/test_and_test_only_annotation.move new file mode 100644 index 0000000000000..7da60126e45cf --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/test_and_test_only_annotation.move @@ -0,0 +1,8 @@ +// functions cannot be annotated as both #[test] and #[test_only] +address 0x1 { +module M { + #[test(_a=@0x1, _b=@0x2)] + #[test_only] + public fun boo(_a: signer, _b: signer) { } +} +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/test_filter_function.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/test_filter_function.exp new file mode 100644 index 0000000000000..a2209df6043bf --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/test_filter_function.exp @@ -0,0 +1,7 @@ + +Diagnostics: +error: no function named `bar` found + ┌─ tests/unit_test/notest/test_filter_function.move:6:24 + │ +6 │ public fun foo() { bar() } + │ ^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/test_filter_function.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/test_filter_function.move new file mode 100644 index 0000000000000..33d17ad279ee4 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/test_filter_function.move @@ -0,0 +1,11 @@ +// #[test_only] functions should be filtered out in non-test mode +address 0x1 { +module M { + // This should cause an unbound function error in non-test mode as `bar` + // was filtered out + public fun foo() { bar() } + + #[test_only] + public fun bar() { } +} +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/test_filter_struct.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/test_filter_struct.exp new file mode 100644 index 0000000000000..c6fa9afc333fe --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/test_filter_struct.exp @@ -0,0 +1,13 @@ + +Diagnostics: +error: undeclared `0x1::M::Foo` + ┌─ tests/unit_test/notest/test_filter_struct.move:9:23 + │ +9 │ public fun foo(): Foo { + │ ^^^ + +error: undeclared struct `M::Foo` + ┌─ tests/unit_test/notest/test_filter_struct.move:10:9 + │ +10 │ Foo {} + │ ^^^ diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/test_filter_struct.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/test_filter_struct.move new file mode 100644 index 0000000000000..553671ab01b5d --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/test_filter_struct.move @@ -0,0 +1,13 @@ +// #[test_only] structs should be filtered out in non-test mode +address 0x1 { +module M { + #[test_only] + struct Foo {} + + // This should cause an unbound type error in non-test mode as the Foo + // struct declaration was filtered out + public fun foo(): Foo { + Foo {} + } +} +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/valid_test_module.move b/third_party/move/move-compiler-v2/tests/unit_test/notest/valid_test_module.move new file mode 100644 index 0000000000000..29a03880235d9 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/valid_test_module.move @@ -0,0 +1,50 @@ +// Make sure that legal usage is allowed +module 0x1::M { + // test-only struct + #[test_only] + struct Foo {} + + public fun foo() { } + + // test-only struct used in a test-only function + #[test_only] + public fun bar(): Foo { Foo{} } + + // tests with no arguments are allowed + #[test] + public fun go() { } + + // proper number of signers, and correct parameter names + #[test(_a=@0x1)] + public fun a(_a: signer) { } + + // multiple signers are supported + #[test(_a=@0x1, _b=@0x2)] + public fun b(_a: signer, _b: signer) { } + + // multiple attributes are supported in the same annotation + #[test(_a=@0x1, _b=@0x2), expected_failure] + public fun c(_a: signer, _b: signer) { } + + // Can also break them apart into separate annotations + #[test(_a=@0x1, _b=@0x2)] + #[expected_failure] + public fun d(_a: signer, _b: signer) { } + + // Can assign abort codes + #[test(_a=@0x1, _b=@0x2)] + #[expected_failure(abort_code=5, location=0x1::M)] + public fun e(_a: signer, _b: signer) { } + + // singe annotation with multiple attributes and an abort code assignment + #[test(_a=@0x1, _b=@0x2), expected_failure(abort_code=5, location=0x1::M)] + public fun g(_a: signer, _b: signer) { } + + // single annotation without any arguments and an abort code assignment + #[test, expected_failure(abort_code=5, location=0x1::M)] + public fun h() { } + + // single annotation with no arguments and no abort code annotation + #[test, expected_failure] + public fun i() { } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/attribute_location.move b/third_party/move/move-compiler-v2/tests/unit_test/test/attribute_location.move new file mode 100644 index 0000000000000..2ece812bb8ac1 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/attribute_location.move @@ -0,0 +1,33 @@ +#[test_only] +address 0x42 { +module A { + struct T {} +} +} + +#[test_only] +module 0x42::M { +} + +module 0x42::N { + #[test_only] + friend 0x42::M; + + #[test_only] + use 0x42::A; + + #[test_only] + const C: u64 = 0; + + #[test_only] + struct S { f: A::T } + + #[test_only] + fun foo() {} +} + +module 0x42::Z { + #[test] + #[expected_failure(abort_code = 0, location = 0x42::Z )] + fun foo() { abort 0 } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/attribute_location_invalid.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/attribute_location_invalid.exp new file mode 100644 index 0000000000000..2cc71f4441246 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/attribute_location_invalid.exp @@ -0,0 +1,25 @@ + +Diagnostics: +error: unable to generate test + ┌─ tests/unit_test/test/attribute_location_invalid.move:1:3 + │ +1 │ #[test_only] + │ ^^^^^^^^^ Testing attributes are not allowed in scripts. + +error: invalid attribute + ┌─ tests/unit_test/test/attribute_location_invalid.move:6:3 + │ +6 │ #[test] + │ ^^^^ + │ │ + │ Attribute 'test' is not expected with a module + │ Expected to be used with one of the following: function + +error: invalid attribute + ┌─ tests/unit_test/test/attribute_location_invalid.move:10:7 + │ +10 │ #[expected_failure(abort_code = 0)] + │ ^^^^^^^^^^^^^^^^ + │ │ + │ Attribute 'expected_failure' is not expected with a struct + │ Expected to be used with one of the following: function diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/attribute_location_invalid.move b/third_party/move/move-compiler-v2/tests/unit_test/test/attribute_location_invalid.move new file mode 100644 index 0000000000000..e87b8b22b27ed --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/attribute_location_invalid.move @@ -0,0 +1,12 @@ +#[test_only] +script { + fun main() {} +} + +#[test] +module 0x42::M {} + +module 0x42::N { + #[expected_failure(abort_code = 0)] + struct S {} +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/cross_module_members.move b/third_party/move/move-compiler-v2/tests/unit_test/test/cross_module_members.move new file mode 100644 index 0000000000000..40b60250e6b5e --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/cross_module_members.move @@ -0,0 +1,24 @@ +// Check that test_only filtering and calling is supported across modules and +// different types of module members +address 0x1 { +module A { + #[test_only] + struct Foo has drop {} + + #[test_only] + public fun build_foo(): Foo { Foo {} } +} + +module B { + #[test_only] + use 0x1::A::{Self, Foo}; + + #[test_only] + fun x(_: Foo) { } + + #[test] + fun tester() { + x(A::build_foo()) + } +} +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/cross_module_members_non_test_function.move b/third_party/move/move-compiler-v2/tests/unit_test/test/cross_module_members_non_test_function.move new file mode 100644 index 0000000000000..1cb0df8ff9f9a --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/cross_module_members_non_test_function.move @@ -0,0 +1,27 @@ +// check that `use`'s are filtered out correctly in non-test mode +address 0x1 { +module A { + struct Foo has drop {} + + public fun build_foo(): Foo { Foo {} } +} + +module B { + #[test_only] + use 0x1::A::{Self, Foo}; + + #[test_only] + fun x(_: Foo) { } + + #[test] + fun tester() { + x(A::build_foo()) + } + + // this should fail find the A module in non-test mode as the use statement + // for `A` is test_only. + public fun bad(): Foo { + A::build_foo() + } +} +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/cross_module_test_only_module.move b/third_party/move/move-compiler-v2/tests/unit_test/test/cross_module_test_only_module.move new file mode 100644 index 0000000000000..90bf3320c6b8f --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/cross_module_test_only_module.move @@ -0,0 +1,16 @@ +// check that modules that are annotated as test_only are filtered out correctly +address 0x1 { +#[test_only] +module M { + public fun foo() { } +} + +module Tests { + // this use should cause an unbound module error as M should be filtered out + use 0x1::M; + + fun bar() { + M::foo() + } +} +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_bad_value.move b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_bad_value.move new file mode 100644 index 0000000000000..bc113722c826e --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_bad_value.move @@ -0,0 +1,25 @@ +// check that invalid abort_code values cannot be assigned +module 0x1::A { + #[test_only] + struct Foo has drop {} + + #[test] + #[expected_failure(abort_code=true)] + fun assign_boolean_abort_code() { } + + #[test] + #[expected_failure(abort_code=x"")] + fun assign_hexbyte_abort_code() { } + + #[test] + #[expected_failure(abort_code=b"")] + fun assign_byte_abort_code() { } + + #[test] + #[expected_failure(abort_code=Foo)] + fun assign_struct_abort_code() { } + + #[test] + #[expected_failure(abort_code=@0xC0FFEE)] + fun assign_address_abort_code() { } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_constants.move b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_constants.move new file mode 100644 index 0000000000000..3ecbcdeddb24d --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_constants.move @@ -0,0 +1,33 @@ +module 0x2::m { + const C: u64 = 0 + 1 + 2; +} + +// check that constants can be used +module 0x1::A { + #[test_only] + use 0x2::m as x; + + const C0: u64 = 0; + #[test_only] + const C1: u64 = 0; + + #[test] + #[expected_failure(abort_code=C0)] + fun use_c0() { } + + #[test] + #[expected_failure(abort_code=C1)] + fun use_c1() { } + + #[test] + #[expected_failure(abort_code=x::C)] + fun use_through_alias() { } + + #[test] + #[expected_failure(abort_code=0x1::A::C0)] + fun use_explicit_internal() { } + + #[test] + #[expected_failure(abort_code=0x2::m::C)] + fun use_explicit_external() { } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_constants_invalid.move b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_constants_invalid.move new file mode 100644 index 0000000000000..60c3aac5227c8 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_constants_invalid.move @@ -0,0 +1,19 @@ +module 0x2::m { + const C: u8 = 0 + 1 + 2; +} + +// check invalid constant usage +module 0x1::A { + + #[test] + #[expected_failure(abort_code=0x2::m::C)] + fun not_u64() { } + + #[test] + #[expected_failure(abort_code=0x2::x::C)] + fun unbound_module() { } + + #[test] + #[expected_failure(abort_code=0x1::A::C0)] + fun unbound_constant() { } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_invalid_literals.move b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_invalid_literals.move new file mode 100644 index 0000000000000..511dd24586332 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_invalid_literals.move @@ -0,0 +1,21 @@ +// check that only non-annotated integer literals and u64s can be assigned to +// abort codes +address 0x1 { +module M { + #[test] + #[expected_failure(abort_code=0, location=0x1::M)] + fun ok1() { } + + #[test] + #[expected_failure(abort_code=0u64, location=0x1::M)] + fun ok2() { } + + #[test] + #[expected_failure(abort_code=0u8, location=0x1::M)] + fun fail_annot1() { } + + #[test] + #[expected_failure(abort_code=0u128, location=0x1::M)] + fun fail_annot3() { } +} +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_not_test.move b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_not_test.move new file mode 100644 index 0000000000000..dc0a6a618bde7 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_not_test.move @@ -0,0 +1,8 @@ +// expected_failure attributes can only be placed on #[test] functions +module 0x1::A { + #[expected_failure] + fun foo() { } + + #[test_only, expected_failure] + fun bar() { } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_on_non_function.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_on_non_function.exp new file mode 100644 index 0000000000000..d4af8c6017545 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_on_non_function.exp @@ -0,0 +1,28 @@ + +Diagnostics: +error: invalid attribute + ┌─ tests/unit_test/test/expected_failure_on_non_function.move:3:7 + │ +3 │ #[expected_failure] + │ ^^^^^^^^^^^^^^^^ + │ │ + │ Attribute 'expected_failure' is not expected with a struct + │ Expected to be used with one of the following: function + +error: invalid attribute + ┌─ tests/unit_test/test/expected_failure_on_non_function.move:6:7 + │ +6 │ #[expected_failure] + │ ^^^^^^^^^^^^^^^^ + │ │ + │ Attribute 'expected_failure' is not expected with a use + │ Expected to be used with one of the following: function + +error: invalid attribute + ┌─ tests/unit_test/test/expected_failure_on_non_function.move:9:7 + │ +9 │ #[expected_failure] + │ ^^^^^^^^^^^^^^^^ + │ │ + │ Attribute 'expected_failure' is not expected with a constant + │ Expected to be used with one of the following: function diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_on_non_function.move b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_on_non_function.move new file mode 100644 index 0000000000000..94822f1b4b21d --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_on_non_function.move @@ -0,0 +1,13 @@ +// expected_failure attributes can only be placed on #[test] functions +module 0x1::A { + #[expected_failure] + struct Foo {} + + #[expected_failure] + use 0x1::A; + + #[expected_failure] + const C: u64 = 0; + + struct Bar { f: A::Foo } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_out_of_range_value.move b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_out_of_range_value.move new file mode 100644 index 0000000000000..1564dee73fbca --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_out_of_range_value.move @@ -0,0 +1,19 @@ +// abort_code numbers need to remain in the u64 range +address 0x1 { +module M { + // at u64::max - 1, OK + #[test] + #[expected_failure(abort_code=18446744073709551614)] + fun ok() { } + + // at u64::max, OK + #[test] + #[expected_failure(abort_code=18446744073709551615)] + fun at_max_ok() { } + + // at u64::max + 1, raise an error + #[test] + #[expected_failure(abort_code=18446744073709551616)] + fun past_max_should_fail() { } +} +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/extra_attributes.move b/third_party/move/move-compiler-v2/tests/unit_test/test/extra_attributes.move new file mode 100644 index 0000000000000..11ff5533c4f37 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/extra_attributes.move @@ -0,0 +1,26 @@ +// tests non-abort related execution failures +module 0x1::n {} +module 0x1::m { + #[test_only] + use 0x1::n; + + #[test] + #[expected_failure(vector_error, location=std::vector, hello=0)] + fun t0() { } + + #[test] + #[expected_failure(arithmetic_error, location=n, wowza)] + fun t1() { } + + #[test] + #[expected_failure(out_of_gas, location=Self, so_many_attrs)] + fun t2() { } + + #[test] + #[expected_failure(major_status=4004, an_attr_here_is_unused, location=Self)] + fun t3() { } + + #[test] + #[expected_failure(major_status=4016, minor_code=0, location=Self)] + fun t4() { } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/extra_attributes2.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/extra_attributes2.exp new file mode 100644 index 0000000000000..46fae5f7ace9b --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/extra_attributes2.exp @@ -0,0 +1,25 @@ + +Diagnostics: +error: invalid attribute + ┌─ tests/unit_test/test/extra_attributes2.move:9:38 + │ +9 │ #[expected_failure(abort_code=3, test, location=Self)] + │ ^^^^ Attribute 'test' is not expected in a nested attribute position + +error: invalid attribute + ┌─ tests/unit_test/test/extra_attributes2.move:13:38 + │ +13 │ #[expected_failure(vector_error, test_only, location=Self)] + │ ^^^^^^^^^ Attribute 'test_only' is not expected in a nested attribute position + +error: invalid attribute + ┌─ tests/unit_test/test/extra_attributes2.move:17:24 + │ +17 │ #[expected_failure(bytecode_instruction, location=Self)] + │ ^^^^^^^^^^^^^^^^^^^^ Attribute 'bytecode_instruction' is not expected in a nested attribute position + +error: invalid attribute + ┌─ tests/unit_test/test/extra_attributes2.move:21:24 + │ +21 │ #[expected_failure(verify_only)] + │ ^^^^^^^^^^^ Attribute 'verify_only' is not expected in a nested attribute position diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/extra_attributes2.move b/third_party/move/move-compiler-v2/tests/unit_test/test/extra_attributes2.move new file mode 100644 index 0000000000000..ba09afd866987 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/extra_attributes2.move @@ -0,0 +1,23 @@ +// tests non-abort related execution failures with errors in attributes +module 0x1::n {} +module 0x1::m { + #[test] + #[expected_failure(arithmetic_error, location=Self)] + fun t5() { } + + #[test] + #[expected_failure(abort_code=3, test, location=Self)] + fun t6() { } + + #[test] + #[expected_failure(vector_error, test_only, location=Self)] + fun t7() { } + + #[test_only] + #[expected_failure(bytecode_instruction, location=Self)] + fun t8() { } + + #[test] + #[expected_failure(verify_only)] + fun t9() { } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/invalid_expected_code_name.move b/third_party/move/move-compiler-v2/tests/unit_test/test/invalid_expected_code_name.move new file mode 100644 index 0000000000000..c81a2f6db7dda --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/invalid_expected_code_name.move @@ -0,0 +1,14 @@ +// only "abort_code" can be used as the expected_failure abort code assignment name +module 0x1::M { + #[test] + #[expected_failure(cod=1)] + fun no() {} + + #[test] + #[expected_failure(code=1)] + fun nope() {} + + #[test] + #[expected_failure(abort_cod=1)] + fun noo() {} +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/invalid_expected_failure_name.move b/third_party/move/move-compiler-v2/tests/unit_test/test/invalid_expected_failure_name.move new file mode 100644 index 0000000000000..8d20123ca9c76 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/invalid_expected_failure_name.move @@ -0,0 +1,6 @@ +// straight assignment of an abort code to the expected_failure attribute isn't allowed +module 0x1::M { + #[test] + #[expected_failure=1] + fun f() { } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/multiple_errors.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/multiple_errors.exp new file mode 100644 index 0000000000000..9fa6a051dc11f --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/multiple_errors.exp @@ -0,0 +1,17 @@ + +Diagnostics: +error: duplicate declaration, item, or annotation + ┌─ tests/unit_test/test/multiple_errors.move:27:7 + │ +26 │ #[test(_a=@0x1)] + │ ---- Attribute previously given here +27 │ #[test(_b=@0x2)] + │ ^^^^^^^^^^^^^ Duplicate attribute 'test' attached to the same item + +error: duplicate declaration, item, or annotation + ┌─ tests/unit_test/test/multiple_errors.move:42:7 + │ +41 │ #[expected_failure] + │ ---------------- Attribute previously given here +42 │ #[expected_failure] + │ ^^^^^^^^^^^^^^^^ Duplicate attribute 'expected_failure' attached to the same item diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/multiple_errors.move b/third_party/move/move-compiler-v2/tests/unit_test/test/multiple_errors.move new file mode 100644 index 0000000000000..b16f86093c5b9 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/multiple_errors.move @@ -0,0 +1,45 @@ +// test that we handle multiple errors in the same file correctly and don't stop at the first one +address 0x1 { +module M { + #[test_only] + struct Foo {} + + public fun foo() { } + + #[test_only] + public fun bar() { } + + #[test] + public fun go() { } + + #[test(_a=@0x1)] + public fun a(_a: signer) { } + + // failure: invalid value in test parameter assignment + #[test(_a=Foo)] + public fun b(_a: signer) { } + + #[test(_a=@0x1, _b=@0x2)] + public fun c(_a: signer, _b: signer) { } + + // failure: double annotation + #[test(_a=@0x1)] + #[test(_b=@0x2)] + public fun d(_a: signer, _b: signer) { } + + // failure: annotated as both test and test_only + #[test(_a=@0x1)] + #[test_only] + public fun e(_a: signer, _b: signer) { } + + // failure: invalid number of signer arguments + #[test(_a=@0x1)] + public fun f(_a: signer, _b: signer) { } + + // failure: double annotation + #[test(_a=@0x1)] + #[expected_failure] + #[expected_failure] + public fun g(_a: signer, _b: signer) { } +} +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/multiple_test_annotations.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/multiple_test_annotations.exp new file mode 100644 index 0000000000000..bea66cf6a56ed --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/multiple_test_annotations.exp @@ -0,0 +1,17 @@ + +Diagnostics: +error: duplicate declaration, item, or annotation + ┌─ tests/unit_test/test/multiple_test_annotations.move:6:7 + │ +5 │ #[test(_a=@0x1)] + │ ---- Attribute previously given here +6 │ #[test(_b=@0x2)] + │ ^^^^^^^^^^^^^ Duplicate attribute 'test' attached to the same item + +error: duplicate declaration, item, or annotation + ┌─ tests/unit_test/test/multiple_test_annotations.move:10:7 + │ + 9 │ #[test] + │ ---- Attribute previously given here +10 │ #[test(_a=@0x1, _b=@0x2)] + │ ^^^^^^^^^^^^^^^^^^^^^^ Duplicate attribute 'test' attached to the same item diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/multiple_test_annotations.move b/third_party/move/move-compiler-v2/tests/unit_test/test/multiple_test_annotations.move new file mode 100644 index 0000000000000..e5502ad96a084 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/multiple_test_annotations.move @@ -0,0 +1,13 @@ +// cannot have multiple #[test] attributes. Only one test attribute is allowed, +// and all signer arguments need to be assigned in that attribute. +address 0x1 { +module M { + #[test(_a=@0x1)] + #[test(_b=@0x2)] + public fun a(_a: signer, _b: signer) { } + + #[test] + #[test(_a=@0x1, _b=@0x2)] + public fun b(_a: signer, _b: signer) { } +} +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/named_address_no_value_in_annotation.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/named_address_no_value_in_annotation.exp new file mode 100644 index 0000000000000..ecf5c7f153fe3 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/named_address_no_value_in_annotation.exp @@ -0,0 +1,7 @@ + +Diagnostics: +error: address with no value + ┌─ tests/unit_test/test/named_address_no_value_in_annotation.move:2:18 + │ +2 │ #[test(_a = @UnboundAddr)] + │ ^^^^^^^^^^^ address 'UnboundAddr' is not assigned a value. Try assigning it a value when calling the compiler diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/named_address_no_value_in_annotation.move b/third_party/move/move-compiler-v2/tests/unit_test/test/named_address_no_value_in_annotation.move new file mode 100644 index 0000000000000..b820da2ddc31b --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/named_address_no_value_in_annotation.move @@ -0,0 +1,4 @@ +module 0x1::M { + #[test(_a = @UnboundAddr)] + fun test(_a: signer) { } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_invalid_assignment.move b/third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_invalid_assignment.move new file mode 100644 index 0000000000000..ce614152846e9 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_invalid_assignment.move @@ -0,0 +1,32 @@ +// tests non-abort related execution failures +// invalid assignment +module 0x1::n {} +module 0x1::m { + #[test_only] + use 0x1::n; + + #[test] + #[expected_failure(vector_error=0, location=std::vector)] + fun t0() { } + + #[test] + #[expected_failure(vector_error, minor_status=x"", location=std::vector)] + fun t1() { } + + #[test] + #[expected_failure(arithmetic_error=@0, location=n)] + fun t2() { } + + #[test] + #[expected_failure(out_of_gas=bool, location=Self)] + fun t3() { } + + #[test] + #[expected_failure(major_status=4004u128, location=Self)] + fun t4() { } + + #[test] + #[expected_failure(major_status=4016, minor_status=b"", location=Self)] + fun t5() { } + +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_invalid_location.move b/third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_invalid_location.move new file mode 100644 index 0000000000000..786652248169f --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_invalid_location.move @@ -0,0 +1,41 @@ +// tests non-abort related execution failures +// missing or invalid location +module 0x1::m { + + #[test] + #[expected_failure(vector_error)] + fun t0() { } + + #[test] + #[expected_failure(arithmetic_error)] + fun t1() { } + + #[test] + #[expected_failure(out_of_gas)] + fun t2() { } + + #[test] + #[expected_failure(major_status=4004)] + fun t3() { } + + #[test] + #[expected_failure(major_status=4016, minor_code=0)] + fun t4() { } + + #[test] + #[expected_failure(vector_error, location=x)] + fun u0() { } + + #[test] + #[expected_failure(out_of_gas, location=0x1::m::t0)] + fun u2() { } + + #[test] + #[expected_failure(major_status=4004, location=self)] + fun u3() { } + + #[test] + #[expected_failure(major_status=4016, minor_status=0, location=0)] + fun u4() { } + +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_invalid_location_module.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_invalid_location_module.exp new file mode 100644 index 0000000000000..dda6ecfe8a0f9 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_invalid_location_module.exp @@ -0,0 +1,7 @@ + +Diagnostics: +error: unbound module + ┌─ tests/unit_test/test/other_failures_invalid_location_module.move:6:51 + │ +6 │ #[expected_failure(arithmetic_error, location=0x2::m)] + │ ^^^^^^ Unbound module '0x2::m' diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_invalid_location_module.move b/third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_invalid_location_module.move new file mode 100644 index 0000000000000..7b5cd5a42b89b --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_invalid_location_module.move @@ -0,0 +1,9 @@ +// tests non-abort related execution failures +// invalid module in location +module 0x1::m { + + #[test] + #[expected_failure(arithmetic_error, location=0x2::m)] + fun u1() { } + +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_valid.move b/third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_valid.move new file mode 100644 index 0000000000000..c04e9d5c3155e --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_valid.move @@ -0,0 +1,27 @@ +// tests non-abort related execution failures +module 0x1::n {} +module 0x1::m { + #[test_only] + use 0x1::n; + + #[test] + #[expected_failure(vector_error, location=std::vector)] + fun t0() { } + + #[test] + #[expected_failure(arithmetic_error, location=n)] + fun t1() { } + + #[test] + #[expected_failure(out_of_gas, location=Self)] + fun t2() { } + + #[test] + #[expected_failure(major_status=4004, location=Self)] + fun t3() { } + + #[test] + #[expected_failure(major_status=4016, minor_status=0, location=Self)] + fun t4() { } + +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/script_with_multiple_on_main.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/script_with_multiple_on_main.exp new file mode 100644 index 0000000000000..c6cbbb5ba6b51 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/script_with_multiple_on_main.exp @@ -0,0 +1,19 @@ + +Diagnostics: +error: unable to generate test + ┌─ tests/unit_test/test/script_with_multiple_on_main.move:4:7 + │ +4 │ #[expected_failure] + │ ^^^^^^^^^^^^^^^^ Testing attributes are not allowed in scripts. + +error: unable to generate test + ┌─ tests/unit_test/test/script_with_multiple_on_main.move:5:7 + │ +5 │ #[test_only, test] + │ ^^^^^^^^^ Testing attributes are not allowed in scripts. + +error: unable to generate test + ┌─ tests/unit_test/test/script_with_multiple_on_main.move:5:18 + │ +5 │ #[test_only, test] + │ ^^^^ Testing attributes are not allowed in scripts. diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/script_with_multiple_on_main.move b/third_party/move/move-compiler-v2/tests/unit_test/test/script_with_multiple_on_main.move new file mode 100644 index 0000000000000..7bd77e2b0d2eb --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/script_with_multiple_on_main.move @@ -0,0 +1,7 @@ +// test-related attributes are not allowed in and/or on scripts. We should get an error +// pointing to each one of the attributes in this test. Test annotations inside of a script. +script { + #[expected_failure] + #[test_only, test] + fun main() { } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/script_with_multiple_top_level.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/script_with_multiple_top_level.exp new file mode 100644 index 0000000000000..5b6d53c60b399 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/script_with_multiple_top_level.exp @@ -0,0 +1,19 @@ + +Diagnostics: +error: unable to generate test + ┌─ tests/unit_test/test/script_with_multiple_top_level.move:3:3 + │ +3 │ #[test, expected_failure] + │ ^^^^ Testing attributes are not allowed in scripts. + +error: unable to generate test + ┌─ tests/unit_test/test/script_with_multiple_top_level.move:3:9 + │ +3 │ #[test, expected_failure] + │ ^^^^^^^^^^^^^^^^ Testing attributes are not allowed in scripts. + +error: unable to generate test + ┌─ tests/unit_test/test/script_with_multiple_top_level.move:4:3 + │ +4 │ #[test_only] + │ ^^^^^^^^^ Testing attributes are not allowed in scripts. diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/script_with_multiple_top_level.move b/third_party/move/move-compiler-v2/tests/unit_test/test/script_with_multiple_top_level.move new file mode 100644 index 0000000000000..1742f4e6ba2c4 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/script_with_multiple_top_level.move @@ -0,0 +1,7 @@ +// test-related attributes are not allowed in and/or on scripts. We should get an error +// pointing to each one of the attributes in this test. Test annotations on a script. +#[test, expected_failure] +#[test_only] +script { + fun main() { } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/script_with_test_on_main.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/script_with_test_on_main.exp new file mode 100644 index 0000000000000..208a107511fd8 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/script_with_test_on_main.exp @@ -0,0 +1,7 @@ + +Diagnostics: +error: unable to generate test + ┌─ tests/unit_test/test/script_with_test_on_main.move:3:7 + │ +3 │ #[test] + │ ^^^^ Testing attributes are not allowed in scripts. diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/script_with_test_on_main.move b/third_party/move/move-compiler-v2/tests/unit_test/test/script_with_test_on_main.move new file mode 100644 index 0000000000000..596a98be2f2e1 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/script_with_test_on_main.move @@ -0,0 +1,5 @@ +// Test a single annotation inside of a script that isn't allowed. +script { + #[test] + fun main() { } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/script_with_test_top_level.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/script_with_test_top_level.exp new file mode 100644 index 0000000000000..6b95e44326f11 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/script_with_test_top_level.exp @@ -0,0 +1,7 @@ + +Diagnostics: +error: unable to generate test + ┌─ tests/unit_test/test/script_with_test_top_level.move:2:3 + │ +2 │ #[test_only] + │ ^^^^^^^^^ Testing attributes are not allowed in scripts. diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/script_with_test_top_level.move b/third_party/move/move-compiler-v2/tests/unit_test/test/script_with_test_top_level.move new file mode 100644 index 0000000000000..baa84e7525957 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/script_with_test_top_level.move @@ -0,0 +1,5 @@ +// test a single test-related attribute on a script that isn't allowed +#[test_only] +script { + fun main() { } +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/test_and_test_only_annotation.move b/third_party/move/move-compiler-v2/tests/unit_test/test/test_and_test_only_annotation.move new file mode 100644 index 0000000000000..7da60126e45cf --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/test_and_test_only_annotation.move @@ -0,0 +1,8 @@ +// functions cannot be annotated as both #[test] and #[test_only] +address 0x1 { +module M { + #[test(_a=@0x1, _b=@0x2)] + #[test_only] + public fun boo(_a: signer, _b: signer) { } +} +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/test_filter_function.move b/third_party/move/move-compiler-v2/tests/unit_test/test/test_filter_function.move new file mode 100644 index 0000000000000..33d17ad279ee4 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/test_filter_function.move @@ -0,0 +1,11 @@ +// #[test_only] functions should be filtered out in non-test mode +address 0x1 { +module M { + // This should cause an unbound function error in non-test mode as `bar` + // was filtered out + public fun foo() { bar() } + + #[test_only] + public fun bar() { } +} +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/test_filter_struct.move b/third_party/move/move-compiler-v2/tests/unit_test/test/test_filter_struct.move new file mode 100644 index 0000000000000..553671ab01b5d --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/test_filter_struct.move @@ -0,0 +1,13 @@ +// #[test_only] structs should be filtered out in non-test mode +address 0x1 { +module M { + #[test_only] + struct Foo {} + + // This should cause an unbound type error in non-test mode as the Foo + // struct declaration was filtered out + public fun foo(): Foo { + Foo {} + } +} +} diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/valid_test_module.move b/third_party/move/move-compiler-v2/tests/unit_test/test/valid_test_module.move new file mode 100644 index 0000000000000..29a03880235d9 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/valid_test_module.move @@ -0,0 +1,50 @@ +// Make sure that legal usage is allowed +module 0x1::M { + // test-only struct + #[test_only] + struct Foo {} + + public fun foo() { } + + // test-only struct used in a test-only function + #[test_only] + public fun bar(): Foo { Foo{} } + + // tests with no arguments are allowed + #[test] + public fun go() { } + + // proper number of signers, and correct parameter names + #[test(_a=@0x1)] + public fun a(_a: signer) { } + + // multiple signers are supported + #[test(_a=@0x1, _b=@0x2)] + public fun b(_a: signer, _b: signer) { } + + // multiple attributes are supported in the same annotation + #[test(_a=@0x1, _b=@0x2), expected_failure] + public fun c(_a: signer, _b: signer) { } + + // Can also break them apart into separate annotations + #[test(_a=@0x1, _b=@0x2)] + #[expected_failure] + public fun d(_a: signer, _b: signer) { } + + // Can assign abort codes + #[test(_a=@0x1, _b=@0x2)] + #[expected_failure(abort_code=5, location=0x1::M)] + public fun e(_a: signer, _b: signer) { } + + // singe annotation with multiple attributes and an abort code assignment + #[test(_a=@0x1, _b=@0x2), expected_failure(abort_code=5, location=0x1::M)] + public fun g(_a: signer, _b: signer) { } + + // single annotation without any arguments and an abort code assignment + #[test, expected_failure(abort_code=5, location=0x1::M)] + public fun h() { } + + // single annotation with no arguments and no abort code annotation + #[test, expected_failure] + public fun i() { } +} diff --git a/third_party/move/move-compiler-v2/tests/v1.matched b/third_party/move/move-compiler-v2/tests/v1.matched index 5d6a27b19b399..aaf091180c6c3 100644 --- a/third_party/move/move-compiler-v2/tests/v1.matched +++ b/third_party/move/move-compiler-v2/tests/v1.matched @@ -430,3 +430,34 @@ move-compiler/tests/move_check/typing/while_body.exp move-compiler-v2/tests/ch move-compiler/tests/move_check/typing/while_body_invalid.exp move-compiler-v2/tests/checking/typing/while_body_invalid.exp move-compiler/tests/move_check/typing/while_condition.exp move-compiler-v2/tests/checking/typing/while_condition.exp move-compiler/tests/move_check/typing/while_condition_invalid.exp move-compiler-v2/tests/checking/typing/while_condition_invalid.exp +move-compiler/tests/move_check/parser/aptos_stdlib_attributes.exp move-compiler-v2/tests/checking/attributes/aptos_stdlib_attributes.exp +move-compiler/tests/move_check/parser/aptos_stdlib_attributes2.exp move-compiler-v2/tests/checking/attributes/aptos_stdlib_attributes2.exp +move-compiler/tests/move_check/parser/attribute_no_closing_bracket.exp move-compiler-v2/tests/checking/attributes/attribute_no_closing_bracket.exp +move-compiler/tests/move_check/parser/attribute_num_sign_no_bracket.exp move-compiler-v2/tests/checking/attributes/attribute_num_sign_no_bracket.exp +move-compiler/tests/move_check/parser/attribute_placement.exp move-compiler-v2/tests/checking/attributes/attribute_placement.exp +move-compiler/tests/move_check/parser/attribute_variants.exp move-compiler-v2/tests/checking/attributes/attribute_variants.exp +move-compiler/tests/move_check/parser/duplicate_attributes.exp move-compiler-v2/tests/checking/attributes/duplicate_attributes.exp +move-compiler/tests/move_check/skip_attribute_checks/aptos_stdlib_attributes.exp move-compiler-v2/tests/skip_attribute_checks/aptos_stdlib_attributes.exp +move-compiler/tests/move_check/skip_attribute_checks/attribute_no_closing_bracket.exp move-compiler-v2/tests/skip_attribute_checks/attribute_no_closing_bracket.exp +move-compiler/tests/move_check/skip_attribute_checks/duplicate_attributes.exp move-compiler-v2/tests/skip_attribute_checks/duplicate_attributes.exp +move-compiler/tests/move_check/unit_testattribute_location_invalid.exp move-compiler-v2/tests/unit_test/notest/attribute_location_invalid.exp +move-compiler/tests/move_check/unit_testcross_module_members_non_test_function.exp move-compiler-v2/tests/unit_test/notest/cross_module_members_non_test_function.exp +move-compiler/tests/move_check/unit_testcross_module_test_only_module.exp move-compiler-v2/tests/unit_test/notest/cross_module_test_only_module.exp +move-compiler/tests/move_check/unit_testexpected_failure_on_non_function.exp move-compiler-v2/tests/unit_test/notest/expected_failure_on_non_function.exp +move-compiler/tests/move_check/unit_testscript_with_multiple_on_main.exp move-compiler-v2/tests/unit_test/notest/script_with_multiple_on_main.exp +move-compiler/tests/move_check/unit_testscript_with_multiple_top_level.exp move-compiler-v2/tests/unit_test/notest/script_with_multiple_top_level.exp +move-compiler/tests/move_check/unit_testscript_with_test_on_main.exp move-compiler-v2/tests/unit_test/notest/script_with_test_on_main.exp +move-compiler/tests/move_check/unit_testscript_with_test_top_level.exp move-compiler-v2/tests/unit_test/notest/script_with_test_top_level.exp +move-compiler/tests/move_check/unit_testtest_filter_function.exp move-compiler-v2/tests/unit_test/notest/test_filter_function.exp +move-compiler/tests/move_check/unit_testtest_filter_struct.exp move-compiler-v2/tests/unit_test/notest/test_filter_struct.exp +move-compiler/tests/move_check/unit_test/attribute_location_invalid.unit_test.exp move-compiler-v2/tests/unit_test/test/attribute_location_invalid.exp +move-compiler/tests/move_check/unit_test/expected_failure_on_non_function.unit_test.exp move-compiler-v2/tests/unit_test/test/expected_failure_on_non_function.exp +move-compiler/tests/move_check/unit_test/extra_attributes2.unit_test.exp move-compiler-v2/tests/unit_test/test/extra_attributes2.exp +move-compiler/tests/move_check/unit_test/multiple_errors.unit_test.exp move-compiler-v2/tests/unit_test/test/multiple_errors.exp +move-compiler/tests/move_check/unit_test/multiple_test_annotations.unit_test.exp move-compiler-v2/tests/unit_test/test/multiple_test_annotations.exp +move-compiler/tests/move_check/unit_test/named_address_no_value_in_annotation.unit_test.exp move-compiler-v2/tests/unit_test/test/named_address_no_value_in_annotation.exp +move-compiler/tests/move_check/unit_test/other_failures_invalid_location_module.unit_test.exp move-compiler-v2/tests/unit_test/test/other_failures_invalid_location_module.exp +move-compiler/tests/move_check/unit_test/script_with_multiple_on_main.unit_test.exp move-compiler-v2/tests/unit_test/test/script_with_multiple_on_main.exp +move-compiler/tests/move_check/unit_test/script_with_multiple_top_level.unit_test.exp move-compiler-v2/tests/unit_test/test/script_with_multiple_top_level.exp +move-compiler/tests/move_check/unit_test/script_with_test_on_main.unit_test.exp move-compiler-v2/tests/unit_test/test/script_with_test_on_main.exp +move-compiler/tests/move_check/unit_test/script_with_test_top_level.unit_test.exp move-compiler-v2/tests/unit_test/test/script_with_test_top_level.exp diff --git a/third_party/move/move-compiler-v2/tests/v1.unmatched b/third_party/move/move-compiler-v2/tests/v1.unmatched index 7a59477e16b97..0600fe2512c01 100644 --- a/third_party/move/move-compiler-v2/tests/v1.unmatched +++ b/third_party/move/move-compiler-v2/tests/v1.unmatched @@ -225,3 +225,17 @@ move-compiler/tests/move_check/verification/{ single_module_invalid.move, single_module_valid.move, } +move-compiler/tests/move_check/unit_test/{ + cross_module_members_non_test_function.move + expected_failure_bad_value.unit_test + expected_failure_constants_invalid.unit_test + expected_failure_invalid_literals.unit_test + expected_failure_not_test.unit_test + expected_failure_out_of_range_value.unit_test + extra_attributes.unit_test + invalid_expected_code_name.unit_test + invalid_expected_failure_name.unit_test + other_failures_invalid_assignment.unit_test + other_failures_invalid_location.unit_test + test_and_test_only_annotation.unit_test +} diff --git a/third_party/move/move-compiler/tests/move_check/parser/aptos_stdlib_attributes.move b/third_party/move/move-compiler/tests/move_check/parser/aptos_stdlib_attributes.move index 2180c108cb141..a0746a4d37bb9 100644 --- a/third_party/move/move-compiler/tests/move_check/parser/aptos_stdlib_attributes.move +++ b/third_party/move/move-compiler/tests/move_check/parser/aptos_stdlib_attributes.move @@ -1,5 +1,5 @@ // Test that warnings about unknown "#[testonly]" attribute is -// suppressed in apts_std module. +// suppressed in aptos_std module. module aptos_std::module_with_suppressed_warnings { #[a, a(x = 0)] fun foo() {} diff --git a/third_party/move/move-compiler/tests/move_check/skip_attribute_checks/aptos_stdlib_attributes.move b/third_party/move/move-compiler/tests/move_check/skip_attribute_checks/aptos_stdlib_attributes.move index 2180c108cb141..a0746a4d37bb9 100644 --- a/third_party/move/move-compiler/tests/move_check/skip_attribute_checks/aptos_stdlib_attributes.move +++ b/third_party/move/move-compiler/tests/move_check/skip_attribute_checks/aptos_stdlib_attributes.move @@ -1,5 +1,5 @@ // Test that warnings about unknown "#[testonly]" attribute is -// suppressed in apts_std module. +// suppressed in aptos_std module. module aptos_std::module_with_suppressed_warnings { #[a, a(x = 0)] fun foo() {} diff --git a/third_party/move/move-compiler/tests/move_check/to_bytecode/unassigned_address.exp b/third_party/move/move-compiler/tests/move_check/to_bytecode/unassigned_address.exp new file mode 100644 index 0000000000000..2eba6a5c3fc37 --- /dev/null +++ b/third_party/move/move-compiler/tests/move_check/to_bytecode/unassigned_address.exp @@ -0,0 +1,42 @@ +error[E03001]: address with no value + ┌─ tests/move_check/to_bytecode/unassigned_address.move:4:9 + │ +4 │ address UNASSIGNED { + │ ^^^^^^^^^^ address 'UNASSIGNED' is not assigned a value + +error[E03001]: address with no value + ┌─ tests/move_check/to_bytecode/unassigned_address.move:8:8 + │ +8 │ module UNASSIGNED::M { + │ ^^^^^^^^^^ address 'UNASSIGNED' is not assigned a value. Try assigning it a value when calling the compiler + +error[E03001]: address with no value + ┌─ tests/move_check/to_bytecode/unassigned_address.move:10:12 + │ +10 │ friend UNASSIGNED::N; + │ ^^^^^^^^^^ address 'UNASSIGNED' is not assigned a value + +error[E03001]: address with no value + ┌─ tests/move_check/to_bytecode/unassigned_address.move:14:8 + │ +14 │ module UNASSIGNED::N { + │ ^^^^^^^^^^ address 'UNASSIGNED' is not assigned a value. Try assigning it a value when calling the compiler + +error[E03001]: address with no value + ┌─ tests/move_check/to_bytecode/unassigned_address.move:15:16 + │ +15 │ fun bar(): UNASSIGNED::M::S { + │ ^^^^^^^^^^ address 'UNASSIGNED' is not assigned a value + +error[E03001]: address with no value + ┌─ tests/move_check/to_bytecode/unassigned_address.move:16:9 + │ +16 │ UNASSIGNED::M::foo(@UNASSIGNED) + │ ^^^^^^^^^^ address 'UNASSIGNED' is not assigned a value + +error[E03001]: address with no value + ┌─ tests/move_check/to_bytecode/unassigned_address.move:16:29 + │ +16 │ UNASSIGNED::M::foo(@UNASSIGNED) + │ ^^^^^^^^^^ address 'UNASSIGNED' is not assigned a value. Try assigning it a value when calling the compiler + diff --git a/third_party/move/move-compiler/tests/move_check/to_bytecode/unassigned_address.move b/third_party/move/move-compiler/tests/move_check/to_bytecode/unassigned_address.move index adb4bdfe81213..ae4d8ca116c5f 100644 --- a/third_party/move/move-compiler/tests/move_check/to_bytecode/unassigned_address.move +++ b/third_party/move/move-compiler/tests/move_check/to_bytecode/unassigned_address.move @@ -1,18 +1,18 @@ // Tests compilation is stopped for unassigned addresses // Named addresses don't exist at the bytecode level -address A { +address UNASSIGNED { module Ex {} } -module A::M { +module UNASSIGNED::M { struct S {} - friend A::N; + friend UNASSIGNED::N; public(friend) fun foo(_: address): S { S{} } } -module A::N { - fun bar(): A::M::S { - A::M::foo(@A) +module UNASSIGNED::N { + fun bar(): UNASSIGNED::M::S { + UNASSIGNED::M::foo(@UNASSIGNED) } } diff --git a/third_party/move/move-examples/diem-framework/move-packages/core/Move.toml b/third_party/move/move-examples/diem-framework/move-packages/core/Move.toml index ce44f401a5bcf..ee96eaae52835 100644 --- a/third_party/move/move-examples/diem-framework/move-packages/core/Move.toml +++ b/third_party/move/move-examples/diem-framework/move-packages/core/Move.toml @@ -9,5 +9,5 @@ CoreFramework = "0x1" CoreResources = "0xA550C18" [dependencies] -MoveStdlib = { local = "../../../../../move-stdlib" } -MoveNursery = { local = "../../../../../move-stdlib/nursery" } +MoveStdlib = { local = "../../../../move-stdlib" } +MoveNursery = { local = "../../../../move-stdlib/nursery" } diff --git a/third_party/move/move-examples/diem-framework/move-packages/experimental/Move.toml b/third_party/move/move-examples/diem-framework/move-packages/experimental/Move.toml index 0341695ec968d..6a9b509b236ae 100644 --- a/third_party/move/move-examples/diem-framework/move-packages/experimental/Move.toml +++ b/third_party/move/move-examples/diem-framework/move-packages/experimental/Move.toml @@ -13,6 +13,6 @@ CurrencyInfo = "0xA550C18" VMReserved = "0x0" [dependencies] -MoveStdlib = { local = "../../../../../move-stdlib" } +MoveStdlib = { local = "../../../../move-stdlib" } DiemCoreFramework = { local = "../core" } diff --git a/third_party/move/move-examples/diem-framework/move-packages/experimental/sources/MultiToken.move b/third_party/move/move-examples/diem-framework/move-packages/experimental/sources/MultiToken.move index 4106a49d8f712..e637a16befc5e 100644 --- a/third_party/move/move-examples/diem-framework/move-packages/experimental/sources/MultiToken.move +++ b/third_party/move/move-examples/diem-framework/move-packages/experimental/sources/MultiToken.move @@ -157,12 +157,12 @@ module ExperimentalFramework::MultiToken { /// Finds the index of token with the given id in the gallery. fun index_of_token(gallery: &vector>, id: &guid::ID): Option { let i = 0; - let len = vector::length(gallery); + let len1 = vector::length(gallery); while ({spec { invariant i >= 0; - invariant i <= ::len(gallery); + invariant i <= len(gallery); invariant forall k in 0..i: gallery[k].token_id.id != id; - };(i < len)}) { + };(i < len1)}) { if (guid::eq_id(&vector::borrow(gallery, i).token_id, id)) { return option::some(i) }; diff --git a/third_party/move/move-examples/diem-framework/move-packages/experimental/sources/MultiTokenBalance.move b/third_party/move/move-examples/diem-framework/move-packages/experimental/sources/MultiTokenBalance.move index e08acd8164338..c7802616be4b7 100644 --- a/third_party/move/move-examples/diem-framework/move-packages/experimental/sources/MultiTokenBalance.move +++ b/third_party/move/move-examples/diem-framework/move-packages/experimental/sources/MultiTokenBalance.move @@ -97,12 +97,12 @@ module ExperimentalFramework::MultiTokenBalance { /// Finds the index of token with the given id in the gallery. fun index_of_token(gallery: &vector>, id: &guid::ID): Option { let i = 0; - let len = vector::length(gallery); + let len1 = vector::length(gallery); while ({spec { invariant i >= 0; - invariant i <= ::len(gallery); + invariant i <= len(gallery); invariant forall k in 0..i: gallery[k].id != id; - };(i < len)}) { + };(i < len1)}) { if (MultiToken::id(vector::borrow(gallery, i)) == *id) { return option::some(i) }; diff --git a/third_party/move/move-model/src/lib.rs b/third_party/move/move-model/src/lib.rs index d9ad6518e72a5..21de19ede6aec 100644 --- a/third_party/move/move-model/src/lib.rs +++ b/third_party/move/move-model/src/lib.rs @@ -85,6 +85,7 @@ pub fn run_model_builder_in_compiler_mode( skip_attribute_checks: bool, known_attributes: &BTreeSet, language_version: LanguageVersion, + compile_test_code: bool, ) -> anyhow::Result { let to_package_paths = |PackageInfo { sources, @@ -102,7 +103,9 @@ pub fn run_model_builder_in_compiler_mode( language_version, ..ModelBuilderOptions::default() }, - Flags::model_compilation().set_skip_attribute_checks(skip_attribute_checks), + Flags::model_compilation() + .set_skip_attribute_checks(skip_attribute_checks) + .set_keep_testing_functions(compile_test_code), known_attributes, ) } diff --git a/third_party/move/move-prover/src/lib.rs b/third_party/move/move-prover/src/lib.rs index 98f8de874c9a1..9b52f6d3b2a6c 100644 --- a/third_party/move/move-prover/src/lib.rs +++ b/third_party/move/move-prover/src/lib.rs @@ -26,7 +26,6 @@ use move_prover_bytecode_pipeline::{ }; use move_stackless_bytecode::function_target_pipeline::FunctionTargetsHolder; use std::{ - cell::RefCell, fs, path::{Path, PathBuf}, time::Instant, @@ -81,10 +80,11 @@ pub fn run_move_prover_v2( known_attributes: Default::default(), testing: cloned_options.backend.stable_test_output, experiments: vec![], - experiment_cache: RefCell::new(Default::default()), + experiment_cache: Default::default(), sources: cloned_options.move_sources, warn_unused: false, whole_program: false, + compile_test_code: false, }; let mut env = move_compiler_v2::run_move_compiler_for_analysis(error_writer, compiler_options)?; diff --git a/third_party/move/tools/move-package/src/compilation/compiled_package.rs b/third_party/move/tools/move-package/src/compilation/compiled_package.rs index d96786fb7b808..c5eaa4e00020f 100644 --- a/third_party/move/tools/move-package/src/compilation/compiled_package.rs +++ b/third_party/move/tools/move-package/src/compilation/compiled_package.rs @@ -682,6 +682,7 @@ impl CompiledPackage { skip_attribute_checks, known_attributes: known_attributes.clone(), language_version: Some(effective_language_version), + compile_test_code: flags.keep_testing_functions(), ..Default::default() }; compiler_driver_v2(options)? From 36181e92c65020660a98d2041aadaafdc682cf8a Mon Sep 17 00:00:00 2001 From: Vineeth Kashyap Date: Fri, 5 Apr 2024 11:50:21 -0400 Subject: [PATCH 09/36] [compiler-v2] Optimize/bug fix in file format gen when "live after check" was overly conservative (#12780) --- .../function_generator.rs | 20 ++- .../file-format-generator/assign.opt.exp | 8 +- .../generic_call.opt.exp | 2 +- .../file-format-generator/if_else.opt.exp | 6 +- .../tests/file-format-generator/loop.opt.exp | 8 +- .../file-format-generator/operators.opt.exp | 83 +++++----- .../file-format-generator/vector.opt.exp | 49 +++--- .../tests/reference-safety/bug_12756.exp | 2 + .../tests/reference-safety/bug_12756.move | 12 ++ .../reference-safety/bug_12756.no-opt.exp | 2 + .../v1-tests/call_mutual_borrows.exp | 34 +--- .../v1-tests/dereference_full.exp | 34 +--- .../v1-tests/mutate_field.exp | 34 +--- .../reference-safety/v1-tests/mutate_full.exp | 34 +--- .../move/move-compiler-v2/tests/testsuite.rs | 1 + .../args_with_side_effects.exp | 6 +- .../args_with_side_effects.opt.exp | 57 ++++++- .../variable-coalescing/borrowed_var.opt.exp | 50 ++++++ .../tests/variable-coalescing/branch_1.exp | 2 +- .../variable-coalescing/branch_1.opt.exp | 43 ++++- .../variable-coalescing/branch_2.opt.exp | 33 ++++ .../variable-coalescing/branch_3.opt.exp | 33 ++++ ...ch_assigns_then_moves_then_assigns.opt.exp | 76 +++++++++ .../tests/variable-coalescing/bug_12068.exp | 2 +- .../variable-coalescing/bug_12068.opt.exp | 72 ++++++++- .../tests/variable-coalescing/call_1.exp | 12 +- .../tests/variable-coalescing/call_1.opt.exp | 61 +++++++- .../tests/variable-coalescing/call_2.opt.exp | 51 ++++++ .../cant_coalesce_1.opt.exp | 22 +++ .../cant_copy_propagate.opt.exp | 56 +++++++ .../tests/variable-coalescing/conditional.exp | 2 +- .../variable-coalescing/conditional.opt.exp | 30 ++++ .../variable-coalescing/consume_1.opt.exp | 106 +++++++++++++ .../variable-coalescing/consume_2.opt.exp | 68 ++++++++ .../variable-coalescing/consume_3.opt.exp | 66 ++++++++ .../variable-coalescing/consume_4.opt.exp | 72 +++++++++ .../tests/variable-coalescing/consume_5.exp | 4 +- .../variable-coalescing/consume_5.opt.exp | 134 +++++++++++++++- .../cyclic_assignment_without_use.opt.exp | 20 +++ .../cyclic_assignments.opt.exp | 26 ++++ .../variable-coalescing/cyclic_dead_store.exp | 4 +- .../cyclic_dead_store.opt.exp | 106 ++++++++++++- .../dead_assignment_1.opt.exp | 23 +++ .../dead_assignment_2.opt.exp | 17 ++ .../dead_assignment_3.opt.exp | 34 ++++ .../dead_assignment_4.opt.exp | 69 ++++++++ .../variable-coalescing/immut_refs_1.opt.exp | 28 ++++ .../variable-coalescing/immut_refs_2.opt.exp | 33 ++++ .../variable-coalescing/inlining1.opt.exp | 18 +++ .../variable-coalescing/intermingled_1.exp | 2 +- .../intermingled_1.opt.exp | 30 ++++ .../variable-coalescing/intermingled_2.exp | 4 +- .../intermingled_2.opt.exp | 51 ++++-- .../intermingled_3.opt.exp | 30 ++++ .../tests/variable-coalescing/loop_1.exp | 2 +- .../tests/variable-coalescing/loop_1.opt.exp | 65 +++++++- .../tests/variable-coalescing/loop_2.exp | 2 +- .../tests/variable-coalescing/loop_2.opt.exp | 65 +++++++- .../variable-coalescing/multi_assigns.opt.exp | 24 +++ .../variable-coalescing/mut_refs_1.opt.exp | 31 ++++ .../variable-coalescing/mut_refs_2.opt.exp | 48 ++++++ .../non_overlapping_vars1.opt.exp | 38 +++++ .../non_overlapping_vars_diff_type.opt.exp | 38 +++++ .../variable-coalescing/overlapping_vars.exp | 10 +- .../overlapping_vars.opt.exp | 18 +++ .../variable-coalescing/reassigned_var.exp | 2 +- .../reassigned_var.opt.exp | 39 ++++- .../variable-coalescing/self_assigns.exp | 4 +- .../variable-coalescing/self_assigns.opt.exp | 147 +++++++++++++++++- .../variable-coalescing/seq_kills_1.opt.exp | 37 +++++ .../variable-coalescing/seq_kills_2.opt.exp | 37 +++++ .../sequential_assign_struct.opt.exp | 32 ++++ .../simple_sequential_assign.opt.exp | 32 ++++ .../straight_line_kills.exp | 2 +- .../straight_line_kills.opt.exp | 36 ++++- .../tests/variable-coalescing/swap.opt.exp | 28 ++++ .../variable-coalescing/swap_in_a_loop.exp | 2 +- .../swap_in_a_loop.opt.exp | 70 ++++++++- .../variable-coalescing/unused_add.opt.exp | 14 ++ 79 files changed, 2406 insertions(+), 299 deletions(-) create mode 100644 third_party/move/move-compiler-v2/tests/reference-safety/bug_12756.exp create mode 100644 third_party/move/move-compiler-v2/tests/reference-safety/bug_12756.move create mode 100644 third_party/move/move-compiler-v2/tests/reference-safety/bug_12756.no-opt.exp diff --git a/third_party/move/move-compiler-v2/src/file_format_generator/function_generator.rs b/third_party/move/move-compiler-v2/src/file_format_generator/function_generator.rs index 63661114094e5..26aba25feccb4 100644 --- a/third_party/move/move-compiler-v2/src/file_format_generator/function_generator.rs +++ b/third_party/move/move-compiler-v2/src/file_format_generator/function_generator.rs @@ -793,7 +793,8 @@ impl<'a> FunctionGenerator<'a> { // Copy the temporary if it is copyable and still used after this code point, or // if it appears again in temps_to_push. if fun_ctx.is_copyable(*temp) - && (ctx.is_alive_after(*temp) || temps_to_push[pos + 1..].contains(temp)) + && (ctx.is_alive_after(*temp, true) + || temps_to_push[pos + 1..].contains(temp)) { self.emit(FF::Bytecode::CopyLoc(local)) } else { @@ -832,7 +833,7 @@ impl<'a> FunctionGenerator<'a> { let mut stack_to_flush = self.stack.len(); for temp in temps { if let Some(pos) = self.stack.iter().position(|t| t == temp) { - if ctx.is_alive_after(*temp) { + if ctx.is_alive_after(*temp, true) { // Determine new lowest point to which we need to flush stack_to_flush = std::cmp::min(stack_to_flush, pos); } @@ -866,7 +867,7 @@ impl<'a> FunctionGenerator<'a> { while self.stack.len() > top { let temp = self.stack.pop().unwrap(); if before && ctx.is_alive_before(temp) - || !before && ctx.is_alive_after(temp) + || !before && ctx.is_alive_after(temp, false) || self.pinned.contains(&temp) { // Only need to save to a local if the temp is still used afterwards @@ -984,8 +985,15 @@ impl<'env> FunctionContext<'env> { } impl<'env> BytecodeContext<'env> { - /// Determine whether the temporary is alive (used) in the reachable code after this point. - pub fn is_alive_after(&self, temp: TempIndex) -> bool { + /// Determine whether `temp` is alive (used) in the reachable code after this point. + /// When `dest_check` is true, we additionally check if `temp` is also written to + /// by the current instruction; if it is, then the definition of `temp` being + /// considered here is killed, making it not alive after this point. + pub fn is_alive_after(&self, temp: TempIndex, dest_check: bool) -> bool { + let bc = &self.fun_ctx.fun.data.code[self.code_offset as usize]; + if dest_check && bc.dests().contains(&temp) { + return false; + } let an = self .fun_ctx .fun @@ -997,7 +1005,7 @@ impl<'env> BytecodeContext<'env> { .unwrap_or(false) } - /// Determine whether the temporary is alive (used) in the reachable code before and until + /// Determine whether `temp` is alive (used) in the reachable code before and until /// this point. pub fn is_alive_before(&self, temp: TempIndex) -> bool { let an = self diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/assign.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/assign.opt.exp index d58a3d430774f..0140492ccc133 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/assign.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/assign.opt.exp @@ -33,12 +33,8 @@ B0: 0: MoveLoc[0](Arg0: S) 1: Unpack[1](S) 2: Unpack[0](T) - 3: StLoc[2](Arg2: u64) - 4: StLoc[1](Arg1: u64) - 5: CopyLoc[1](Arg1: u64) - 6: MoveLoc[2](Arg2: u64) - 7: Add - 8: Ret + 3: Add + 4: Ret } assign_struct(Arg0: &mut S) /* def_idx: 3 */ { B0: diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/generic_call.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/generic_call.opt.exp index 73e24828dbf78..953ed238d97bb 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/generic_call.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/generic_call.opt.exp @@ -6,7 +6,7 @@ module 42.Test { foo(Arg0: u64): u64 /* def_idx: 0 */ { B0: - 0: CopyLoc[0](Arg0: u64) + 0: MoveLoc[0](Arg0: u64) 1: Call identity(u64): u64 2: Ret } diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/if_else.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/if_else.opt.exp index 31b34674b8212..dc3c0ddd0b9fd 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/if_else.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/if_else.opt.exp @@ -14,7 +14,7 @@ B1: 2: LdU64(1) 3: StLoc[2](loc0: u64) 4: MoveLoc[1](Arg1: u64) - 5: CopyLoc[2](loc0: u64) + 5: MoveLoc[2](loc0: u64) 6: Add 7: StLoc[2](loc0: u64) 8: Branch(15) @@ -39,7 +39,7 @@ B1: 2: LdU64(1) 3: StLoc[2](loc0: u64) 4: CopyLoc[1](Arg1: u64) - 5: CopyLoc[2](loc0: u64) + 5: MoveLoc[2](loc0: u64) 6: Add 7: StLoc[2](loc0: u64) 8: Branch(15) @@ -61,7 +61,7 @@ B4: 21: LdU64(2) 22: StLoc[2](loc0: u64) 23: MoveLoc[1](Arg1: u64) - 24: CopyLoc[2](loc0: u64) + 24: MoveLoc[2](loc0: u64) 25: Mul 26: StLoc[2](loc0: u64) 27: Branch(34) diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/loop.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/loop.opt.exp index 40f9d7083279e..3afa0a7453e1d 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/loop.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/loop.opt.exp @@ -24,7 +24,7 @@ B2: 12: LdU64(1) 13: StLoc[1](loc0: u64) 14: MoveLoc[0](Arg0: u64) - 15: CopyLoc[1](loc0: u64) + 15: MoveLoc[1](loc0: u64) 16: Sub 17: StLoc[0](Arg0: u64) 18: Branch(20) @@ -34,7 +34,7 @@ B4: 20: LdU64(1) 21: StLoc[1](loc0: u64) 22: MoveLoc[0](Arg0: u64) - 23: CopyLoc[1](loc0: u64) + 23: MoveLoc[1](loc0: u64) 24: Sub 25: StLoc[0](Arg0: u64) 26: Branch(0) @@ -57,7 +57,7 @@ B1: 6: LdU64(1) 7: StLoc[1](loc0: u64) 8: MoveLoc[0](Arg0: u64) - 9: CopyLoc[1](loc0: u64) + 9: MoveLoc[1](loc0: u64) 10: Sub 11: StLoc[0](Arg0: u64) 12: Branch(14) @@ -100,7 +100,7 @@ B5: 20: LdU64(1) 21: StLoc[1](loc0: u64) 22: MoveLoc[0](Arg0: u64) - 23: CopyLoc[1](loc0: u64) + 23: MoveLoc[1](loc0: u64) 24: Sub 25: StLoc[0](Arg0: u64) 26: Branch(28) diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/operators.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/operators.opt.exp index aff0e0483c8ca..2edb1d9fe51b4 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/operators.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/operators.opt.exp @@ -12,39 +12,32 @@ B0: 2: Sub 3: StLoc[2](loc0: u64) 4: CopyLoc[1](Arg1: u64) - 5: CopyLoc[2](loc0: u64) + 5: MoveLoc[2](loc0: u64) 6: Div - 7: CopyLoc[1](Arg1: u64) + 7: MoveLoc[1](Arg1: u64) 8: Mul - 9: StLoc[1](Arg1: u64) - 10: CopyLoc[1](Arg1: u64) - 11: CopyLoc[0](Arg0: u64) - 12: Mod - 13: StLoc[1](Arg1: u64) - 14: CopyLoc[0](Arg0: u64) - 15: MoveLoc[1](Arg1: u64) - 16: Add - 17: Ret + 9: CopyLoc[0](Arg0: u64) + 10: Mod + 11: StLoc[1](Arg1: u64) + 12: MoveLoc[0](Arg0: u64) + 13: MoveLoc[1](Arg1: u64) + 14: Add + 15: Ret } bits(Arg0: u64, Arg1: u8): u64 /* def_idx: 1 */ { -L2: loc0: u64 B0: 0: CopyLoc[0](Arg0: u64) 1: CopyLoc[1](Arg1: u8) 2: Shl - 3: StLoc[2](loc0: u64) - 4: CopyLoc[2](loc0: u64) + 3: CopyLoc[0](Arg0: u64) + 4: BitAnd 5: CopyLoc[0](Arg0: u64) - 6: BitAnd - 7: CopyLoc[0](Arg0: u64) - 8: MoveLoc[1](Arg1: u8) - 9: Shr - 10: CopyLoc[0](Arg0: u64) - 11: Xor - 12: StLoc[0](Arg0: u64) - 13: CopyLoc[0](Arg0: u64) - 14: BitOr - 15: Ret + 6: MoveLoc[1](Arg1: u8) + 7: Shr + 8: MoveLoc[0](Arg0: u64) + 9: Xor + 10: BitOr + 11: Ret } bools(Arg0: bool, Arg1: bool): bool /* def_idx: 2 */ { L2: loc0: bool @@ -102,7 +95,7 @@ B14: 36: StLoc[2](loc0: bool) 37: Branch(47) B15: - 38: CopyLoc[0](Arg0: bool) + 38: MoveLoc[0](Arg0: bool) 39: Not 40: BrFalse(45) B16: @@ -149,37 +142,33 @@ B2: 10: StLoc[2](loc0: bool) B3: 11: MoveLoc[2](loc0: bool) - 12: BrFalse(21) + 12: BrFalse(19) B4: 13: CopyLoc[0](Arg0: u64) 14: CopyLoc[1](Arg1: u64) 15: Gt - 16: StLoc[2](loc0: bool) - 17: CopyLoc[2](loc0: bool) - 18: Not - 19: StLoc[2](loc0: bool) - 20: Branch(23) + 16: Not + 17: StLoc[2](loc0: bool) + 18: Branch(21) B5: - 21: LdFalse - 22: StLoc[2](loc0: bool) + 19: LdFalse + 20: StLoc[2](loc0: bool) B6: - 23: MoveLoc[2](loc0: bool) - 24: BrFalse(33) + 21: MoveLoc[2](loc0: bool) + 22: BrFalse(29) B7: - 25: MoveLoc[0](Arg0: u64) - 26: MoveLoc[1](Arg1: u64) - 27: Ge - 28: StLoc[2](loc0: bool) - 29: CopyLoc[2](loc0: bool) - 30: Not - 31: StLoc[2](loc0: bool) - 32: Branch(35) + 23: MoveLoc[0](Arg0: u64) + 24: MoveLoc[1](Arg1: u64) + 25: Ge + 26: Not + 27: StLoc[2](loc0: bool) + 28: Branch(31) B8: - 33: LdFalse - 34: StLoc[2](loc0: bool) + 29: LdFalse + 30: StLoc[2](loc0: bool) B9: - 35: MoveLoc[2](loc0: bool) - 36: Ret + 31: MoveLoc[2](loc0: bool) + 32: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/vector.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/vector.opt.exp index 54bc30ffd58d3..6e5f12695ba14 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/vector.opt.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/vector.opt.exp @@ -30,7 +30,7 @@ B2: 12: LdU64(1) 13: StLoc[3](loc1: u64) 14: MoveLoc[2](loc0: u64) - 15: CopyLoc[3](loc1: u64) + 15: MoveLoc[3](loc1: u64) 16: Sub 17: StLoc[2](loc0: u64) B3: @@ -46,7 +46,7 @@ B4: 26: LdU64(1) 27: StLoc[5](loc3: u64) 28: MoveLoc[1](Arg1: u64) - 29: CopyLoc[5](loc3: u64) + 29: MoveLoc[5](loc3: u64) 30: Add 31: StLoc[1](Arg1: u64) 32: CopyLoc[1](Arg1: u64) @@ -73,8 +73,7 @@ B0: test_fold() /* def_idx: 2 */ { L0: loc0: vector L1: loc1: u64 -L2: loc2: bool -L3: loc3: u64 +L2: loc2: u64 B0: 0: LdU64(0) 1: LdConst[1](Vector(U64): [1, 1, 0, 0, 0, 0, 0, 0, 0]) @@ -85,35 +84,33 @@ B0: B1: 6: ImmBorrowLoc[0](loc0: vector) 7: Call 1vector::is_empty(&vector): bool - 8: StLoc[2](loc2: bool) - 9: CopyLoc[2](loc2: bool) - 10: Not - 11: BrFalse(18) + 8: Not + 9: BrFalse(16) B2: - 12: MutBorrowLoc[0](loc0: vector) - 13: VecPopBack(5) - 14: LdU64(0) - 15: StLoc[1](loc1: u64) - 16: Pop - 17: Branch(19) + 10: MutBorrowLoc[0](loc0: vector) + 11: VecPopBack(5) + 12: LdU64(0) + 13: StLoc[1](loc1: u64) + 14: Pop + 15: Branch(17) B3: - 18: Branch(20) + 16: Branch(18) B4: - 19: Branch(6) + 17: Branch(6) B5: - 20: LdU64(0) - 21: StLoc[3](loc3: u64) - 22: MoveLoc[1](loc1: u64) - 23: MoveLoc[3](loc3: u64) - 24: Eq - 25: BrFalse(27) + 18: LdU64(0) + 19: StLoc[2](loc2: u64) + 20: MoveLoc[1](loc1: u64) + 21: MoveLoc[2](loc2: u64) + 22: Eq + 23: BrFalse(25) B6: - 26: Branch(29) + 24: Branch(27) B7: - 27: LdU64(0) - 28: Abort + 25: LdU64(0) + 26: Abort B8: - 29: Ret + 27: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/bug_12756.exp b/third_party/move/move-compiler-v2/tests/reference-safety/bug_12756.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/reference-safety/bug_12756.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/bug_12756.move b/third_party/move/move-compiler-v2/tests/reference-safety/bug_12756.move new file mode 100644 index 0000000000000..aa387290fe336 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/reference-safety/bug_12756.move @@ -0,0 +1,12 @@ +module 0xc0ffee::m { + fun id_mut(r: &mut T): &mut T { + r + } + + fun t0() { + let x = &mut 0; + let y = id_mut(x); + *y; + *x; + } +} diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/bug_12756.no-opt.exp b/third_party/move/move-compiler-v2/tests/reference-safety/bug_12756.no-opt.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/reference-safety/bug_12756.no-opt.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_mutual_borrows.exp b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_mutual_borrows.exp index 749237f5882df..90b32906711cc 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_mutual_borrows.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_mutual_borrows.exp @@ -1,34 +1,2 @@ -============ bytecode verification failed ======== - -Diagnostics: -bug: BYTECODE VERIFICATION FAILED - ┌─ tests/reference-safety/v1-tests/call_mutual_borrows.move:19:17 - │ -19 │ mut_imm(&mut s1.f, &s1.g); - │ ^^^^^^^^^ ICE failed bytecode verifier: VMError { - major_status: BORROWFIELD_EXISTS_MUTABLE_BORROW_ERROR, - sub_status: None, - message: None, - exec_state: None, - location: Module( - ModuleId { - address: 0000000000000000000000000000000000000000000000000000000008675309, - name: Identifier( - "M", - ), - }, - ), - indices: [ - ( - FunctionDefinition, - 5, - ), - ], - offsets: [ - ( - FunctionDefinitionIndex(5), - 24, - ), - ], -} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/dereference_full.exp b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/dereference_full.exp index a19b468ffbdb0..90b32906711cc 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/dereference_full.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/dereference_full.exp @@ -1,34 +1,2 @@ -============ bytecode verification failed ======== - -Diagnostics: -bug: BYTECODE VERIFICATION FAILED - ┌─ tests/reference-safety/v1-tests/dereference_full.move:19:9 - │ -19 │ *x; - │ ^^ ICE failed bytecode verifier: VMError { - major_status: READREF_EXISTS_MUTABLE_BORROW_ERROR, - sub_status: None, - message: None, - exec_state: None, - location: Module( - ModuleId { - address: 0000000000000000000000000000000000000000000000000000000008675309, - name: Identifier( - "M", - ), - }, - ), - indices: [ - ( - FunctionDefinition, - 2, - ), - ], - offsets: [ - ( - FunctionDefinitionIndex(2), - 20, - ), - ], -} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/mutate_field.exp b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/mutate_field.exp index ebe9a27e34b15..90b32906711cc 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/mutate_field.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/mutate_field.exp @@ -1,34 +1,2 @@ -============ bytecode verification failed ======== - -Diagnostics: -bug: BYTECODE VERIFICATION FAILED - ┌─ tests/reference-safety/v1-tests/mutate_field.move:23:9 - │ -23 │ *s = S { f: 0, g: 0 }; - │ ^^^^^^^^^^^^^^^^^^^^^ ICE failed bytecode verifier: VMError { - major_status: WRITEREF_EXISTS_BORROW_ERROR, - sub_status: None, - message: None, - exec_state: None, - location: Module( - ModuleId { - address: 0000000000000000000000000000000000000000000000000000000008675309, - name: Identifier( - "M", - ), - }, - ), - indices: [ - ( - FunctionDefinition, - 2, - ), - ], - offsets: [ - ( - FunctionDefinitionIndex(2), - 38, - ), - ], -} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/mutate_full.exp b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/mutate_full.exp index dfa76ceb41a7f..90b32906711cc 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/mutate_full.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/mutate_full.exp @@ -1,34 +1,2 @@ -============ bytecode verification failed ======== - -Diagnostics: -bug: BYTECODE VERIFICATION FAILED - ┌─ tests/reference-safety/v1-tests/mutate_full.move:25:9 - │ -25 │ *x = 0; - │ ^^^^^^ ICE failed bytecode verifier: VMError { - major_status: WRITEREF_EXISTS_BORROW_ERROR, - sub_status: None, - message: None, - exec_state: None, - location: Module( - ModuleId { - address: 0000000000000000000000000000000000000000000000000000000008675309, - name: Identifier( - "M", - ), - }, - ), - indices: [ - ( - FunctionDefinition, - 2, - ), - ], - offsets: [ - ( - FunctionDefinitionIndex(2), - 33, - ), - ], -} +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/testsuite.rs b/third_party/move/move-compiler-v2/tests/testsuite.rs index 0546fe3098ae0..facbc70e85dca 100644 --- a/third_party/move/move-compiler-v2/tests/testsuite.rs +++ b/third_party/move/move-compiler-v2/tests/testsuite.rs @@ -422,6 +422,7 @@ const TEST_CONFIGS: Lazy> = Lazy::new(|| { INITIAL_BYTECODE_STAGE, "VariableCoalescingAnnotator", "VariableCoalescingTransformer", + "DeadStoreElimination", FILE_FORMAT_STAGE, ]), }, diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/args_with_side_effects.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/args_with_side_effects.exp index 137d6bd9a8365..f5e6cf623195e 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/args_with_side_effects.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/args_with_side_effects.exp @@ -153,7 +153,7 @@ module c0ffee.m { add(Arg0: u64, Arg1: u64): u64 /* def_idx: 0 */ { B0: - 0: CopyLoc[0](Arg0: u64) + 0: MoveLoc[0](Arg0: u64) 1: MoveLoc[1](Arg1: u64) 2: Add 3: Ret @@ -167,11 +167,11 @@ B0: 2: LdU64(1) 3: StLoc[2](loc1: u64) 4: MoveLoc[0](Arg0: u64) - 5: CopyLoc[2](loc1: u64) + 5: MoveLoc[2](loc1: u64) 6: Add 7: StLoc[0](Arg0: u64) 8: MoveLoc[1](loc0: u64) - 9: CopyLoc[0](Arg0: u64) + 9: MoveLoc[0](Arg0: u64) 10: Call add(u64, u64): u64 11: Ret } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/args_with_side_effects.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/args_with_side_effects.opt.exp index c75d1258c7fc1..f5e6cf623195e 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/args_with_side_effects.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/args_with_side_effects.opt.exp @@ -24,6 +24,32 @@ public fun m::test($t0: u64): u64 { 6: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::add($t0: u64, $t1: u64): u64 { + var $t2: u64 + 0: $t2 := +($t0, $t1) + 1: return $t2 +} + + +[variant baseline] +public fun m::test($t0: u64): u64 { + var $t1: u64 + var $t2: u64 + var $t3: u64 + var $t4: u64 + var $t5: u64 + 0: $t2 := copy($t0) + 1: $t5 := 1 + 2: $t4 := +($t0, $t5) + 3: $t0 := move($t4) + 4: $t3 := move($t0) + 5: $t1 := m::add($t2, $t3) + 6: return $t1 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -94,6 +120,31 @@ public fun m::test($t0: u64): u64 { 6: return $t0 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::add($t0: u64, $t1: u64): u64 { + var $t2: u64 [unused] + 0: $t0 := +($t0, $t1) + 1: return $t0 +} + + +[variant baseline] +public fun m::test($t0: u64): u64 { + var $t1: u64 [unused] + var $t2: u64 + var $t3: u64 [unused] + var $t4: u64 [unused] + var $t5: u64 + 0: $t2 := copy($t0) + 1: $t5 := 1 + 2: $t5 := +($t0, $t5) + 3: $t0 := move($t5) + 4: $t0 := m::add($t2, $t0) + 5: return $t0 +} + ============ disassembled file-format ================== // Move bytecode v7 @@ -102,7 +153,7 @@ module c0ffee.m { add(Arg0: u64, Arg1: u64): u64 /* def_idx: 0 */ { B0: - 0: CopyLoc[0](Arg0: u64) + 0: MoveLoc[0](Arg0: u64) 1: MoveLoc[1](Arg1: u64) 2: Add 3: Ret @@ -116,11 +167,11 @@ B0: 2: LdU64(1) 3: StLoc[2](loc1: u64) 4: MoveLoc[0](Arg0: u64) - 5: CopyLoc[2](loc1: u64) + 5: MoveLoc[2](loc1: u64) 6: Add 7: StLoc[0](Arg0: u64) 8: MoveLoc[1](loc0: u64) - 9: CopyLoc[0](Arg0: u64) + 9: MoveLoc[0](Arg0: u64) 10: Call add(u64, u64): u64 11: Ret } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/borrowed_var.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/borrowed_var.opt.exp index dab824754fdf5..a965c2cc62ec0 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/borrowed_var.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/borrowed_var.opt.exp @@ -22,6 +22,31 @@ fun m::test() { 9: return () } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test() { + var $t0: &u64 + var $t1: u64 + var $t2: &u64 + var $t3: &u64 + var $t4: u64 + var $t5: bool + var $t6: u64 + var $t7: u64 + 0: $t1 := 5 + 1: $t0 := borrow_local($t1) + 2: $t2 := move($t0) + 3: drop($t2) + 4: $t4 := 5 + 5: $t3 := borrow_local($t4) + 6: $t0 := move($t3) + 7: $t6 := read_ref($t0) + 8: $t7 := 5 + 9: $t5 := ==($t6, $t7) + 10: return () +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -91,6 +116,31 @@ fun m::test() { 10: return () } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test() { + var $t0: &u64 + var $t1: u64 + var $t2: &u64 + var $t3: &u64 [unused] + var $t4: u64 + var $t5: bool + var $t6: u64 + var $t7: u64 + 0: $t1 := 5 + 1: $t0 := borrow_local($t1) + 2: $t2 := move($t0) + 3: drop($t2) + 4: $t4 := 5 + 5: $t2 := borrow_local($t4) + 6: $t0 := move($t2) + 7: $t6 := read_ref($t0) + 8: $t7 := 5 + 9: $t5 := ==($t6, $t7) + 10: return () +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_1.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_1.exp index 53802fe79e78e..de6e28e6987f7 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_1.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_1.exp @@ -138,7 +138,7 @@ B1: B2: 5: LdU64(1) 6: StLoc[2](loc0: u64) - 7: CopyLoc[1](Arg1: u64) + 7: MoveLoc[1](Arg1: u64) 8: MoveLoc[2](loc0: u64) 9: Add 10: Ret diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_1.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_1.opt.exp index 02550129c7cf3..de6e28e6987f7 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_1.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_1.opt.exp @@ -19,6 +19,27 @@ fun m::foo($t0: bool, $t1: u64): u64 { 10: return $t2 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::foo($t0: bool, $t1: u64): u64 { + var $t2: u64 + var $t3: u64 + var $t4: u64 + var $t5: u64 + 0: $t3 := move($t1) + 1: if ($t0) goto 2 else goto 6 + 2: label L0 + 3: $t4 := 0 + 4: $t3 := move($t4) + 5: goto 7 + 6: label L1 + 7: label L2 + 8: $t5 := 1 + 9: $t2 := +($t3, $t5) + 10: return $t2 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -79,6 +100,26 @@ fun m::foo($t0: bool, $t1: u64): u64 { 10: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::foo($t0: bool, $t1: u64): u64 { + var $t2: u64 [unused] + var $t3: u64 [unused] + var $t4: u64 + var $t5: u64 [unused] + 0: if ($t0) goto 1 else goto 5 + 1: label L0 + 2: $t4 := 0 + 3: $t1 := move($t4) + 4: goto 6 + 5: label L1 + 6: label L2 + 7: $t4 := 1 + 8: $t1 := +($t1, $t4) + 9: return $t1 +} + ============ disassembled file-format ================== // Move bytecode v7 @@ -97,7 +138,7 @@ B1: B2: 5: LdU64(1) 6: StLoc[2](loc0: u64) - 7: CopyLoc[1](Arg1: u64) + 7: MoveLoc[1](Arg1: u64) 8: MoveLoc[2](loc0: u64) 9: Add 10: Ret diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_2.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_2.opt.exp index 5f72b828b95e9..770374d97288d 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_2.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_2.opt.exp @@ -15,6 +15,23 @@ fun m::test($t0: bool, $t1: u64, $t2: u64): u64 { 8: return $t3 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test($t0: bool, $t1: u64, $t2: u64): u64 { + var $t3: u64 + var $t4: u64 + 0: if ($t0) goto 1 else goto 4 + 1: label L0 + 2: $t4 := move($t1) + 3: goto 6 + 4: label L1 + 5: $t4 := move($t2) + 6: label L2 + 7: $t3 := move($t4) + 8: return $t3 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -64,6 +81,22 @@ fun m::test($t0: bool, $t1: u64, $t2: u64): u64 { 8: return $t4 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test($t0: bool, $t1: u64, $t2: u64): u64 { + var $t3: u64 [unused] + var $t4: u64 + 0: if ($t0) goto 1 else goto 4 + 1: label L0 + 2: $t4 := move($t1) + 3: goto 6 + 4: label L1 + 5: $t4 := move($t2) + 6: label L2 + 7: return $t4 +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_3.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_3.opt.exp index 3cda1c9fb46ea..56b6cdeb16656 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_3.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_3.opt.exp @@ -15,6 +15,23 @@ fun m::test($t0: bool, $t1: u64): u64 { 8: return $t2 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test($t0: bool, $t1: u64): u64 { + var $t2: u64 + var $t3: u64 + 0: if ($t0) goto 1 else goto 4 + 1: label L0 + 2: $t3 := move($t1) + 3: goto 6 + 4: label L1 + 5: $t3 := move($t1) + 6: label L2 + 7: $t2 := move($t3) + 8: return $t2 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -63,6 +80,22 @@ fun m::test($t0: bool, $t1: u64): u64 { 8: return $t3 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test($t0: bool, $t1: u64): u64 { + var $t2: u64 [unused] + var $t3: u64 + 0: if ($t0) goto 1 else goto 4 + 1: label L0 + 2: $t3 := move($t1) + 3: goto 6 + 4: label L1 + 5: $t3 := move($t1) + 6: label L2 + 7: return $t3 +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_assigns_then_moves_then_assigns.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_assigns_then_moves_then_assigns.opt.exp index 7c692a5124582..79c5859bbe98a 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_assigns_then_moves_then_assigns.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/branch_assigns_then_moves_then_assigns.opt.exp @@ -42,6 +42,45 @@ fun _0::main() { 25: return () } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun _0::main() { + var $t0: u64 + var $t1: u64 [unused] + var $t2: bool + var $t3: u64 [unused] + var $t4: u64 [unused] + var $t5: u64 + var $t6: u64 [unused] + var $t7: u64 + var $t8: bool + var $t9: u64 + var $t10: u64 + var $t11: u64 + 0: $t2 := true + 1: if ($t2) goto 2 else goto 6 + 2: label L0 + 3: $t5 := 5 + 4: $t0 := move($t5) + 5: goto 9 + 6: label L1 + 7: $t7 := 0 + 8: $t0 := move($t7) + 9: label L2 + 10: $t9 := copy($t0) + 11: $t10 := 5 + 12: $t8 := ==($t9, $t10) + 13: if ($t8) goto 14 else goto 16 + 14: label L3 + 15: goto 19 + 16: label L4 + 17: $t11 := 42 + 18: abort($t11) + 19: label L5 + 20: return () +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -153,6 +192,43 @@ fun _0::main() { 20: return () } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun _0::main() { + var $t0: u64 [unused] + var $t1: u64 [unused] + var $t2: bool + var $t3: u64 [unused] + var $t4: u64 [unused] + var $t5: u64 + var $t6: u64 [unused] + var $t7: u64 + var $t8: bool [unused] + var $t9: u64 [unused] + var $t10: u64 [unused] + var $t11: u64 [unused] + 0: $t2 := true + 1: if ($t2) goto 2 else goto 5 + 2: label L0 + 3: $t5 := 5 + 4: goto 8 + 5: label L1 + 6: $t7 := 0 + 7: $t5 := move($t7) + 8: label L2 + 9: $t7 := 5 + 10: $t2 := ==($t5, $t7) + 11: if ($t2) goto 12 else goto 14 + 12: label L3 + 13: goto 17 + 14: label L4 + 15: $t5 := 42 + 16: abort($t5) + 17: label L5 + 18: return () +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/bug_12068.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/bug_12068.exp index 8ea5857c32071..8461312378afe 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/bug_12068.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/bug_12068.exp @@ -227,7 +227,7 @@ B1: 4: LdU64(1) 5: StLoc[1](loc1: u64) 6: MoveLoc[0](loc0: u64) - 7: CopyLoc[1](loc1: u64) + 7: MoveLoc[1](loc1: u64) 8: Add 9: StLoc[0](loc0: u64) 10: Branch(12) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/bug_12068.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/bug_12068.opt.exp index 2f1b8f9d67283..8461312378afe 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/bug_12068.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/bug_12068.opt.exp @@ -36,6 +36,41 @@ fun m::main() { 24: return () } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::main() { + var $t0: u64 + var $t1: bool + var $t2: u64 + var $t3: u64 + var $t4: bool + var $t5: u64 + var $t6: u64 + 0: $t0 := 0 + 1: label L0 + 2: $t1 := true + 3: if ($t1) goto 4 else goto 9 + 4: label L2 + 5: $t3 := 1 + 6: $t2 := +($t0, $t3) + 7: $t0 := move($t2) + 8: goto 11 + 9: label L3 + 10: goto 11 + 11: label L1 + 12: $t5 := 1 + 13: $t4 := ==($t0, $t5) + 14: if ($t4) goto 15 else goto 17 + 15: label L5 + 16: goto 20 + 17: label L6 + 18: $t6 := 42 + 19: abort($t6) + 20: label L7 + 21: return () +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -139,6 +174,41 @@ fun m::main() { 21: return () } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::main() { + var $t0: u64 + var $t1: bool + var $t2: u64 [unused] + var $t3: u64 + var $t4: bool [unused] + var $t5: u64 [unused] + var $t6: u64 [unused] + 0: $t0 := 0 + 1: label L0 + 2: $t1 := true + 3: if ($t1) goto 4 else goto 9 + 4: label L2 + 5: $t3 := 1 + 6: $t3 := +($t0, $t3) + 7: $t0 := move($t3) + 8: goto 11 + 9: label L3 + 10: goto 11 + 11: label L1 + 12: $t3 := 1 + 13: $t1 := ==($t0, $t3) + 14: if ($t1) goto 15 else goto 17 + 15: label L5 + 16: goto 20 + 17: label L6 + 18: $t0 := 42 + 19: abort($t0) + 20: label L7 + 21: return () +} + ============ disassembled file-format ================== // Move bytecode v7 @@ -157,7 +227,7 @@ B1: 4: LdU64(1) 5: StLoc[1](loc1: u64) 6: MoveLoc[0](loc0: u64) - 7: CopyLoc[1](loc1: u64) + 7: MoveLoc[1](loc1: u64) 8: Add 9: StLoc[0](loc0: u64) 10: Branch(12) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/call_1.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/call_1.exp index 0e1d20af29436..8cb6654d0e563 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/call_1.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/call_1.exp @@ -163,15 +163,11 @@ B0: } test(Arg0: u64): u64 /* def_idx: 1 */ { B0: - 0: CopyLoc[0](Arg0: u64) + 0: MoveLoc[0](Arg0: u64) 1: Call id(u64): u64 - 2: StLoc[0](Arg0: u64) - 3: CopyLoc[0](Arg0: u64) - 4: Call id(u64): u64 - 5: StLoc[0](Arg0: u64) - 6: CopyLoc[0](Arg0: u64) - 7: Call id(u64): u64 - 8: Ret + 2: Call id(u64): u64 + 3: Call id(u64): u64 + 4: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/call_1.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/call_1.opt.exp index 73766f2bdd0f4..8cb6654d0e563 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/call_1.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/call_1.opt.exp @@ -33,6 +33,32 @@ fun m::test($t0: u64): u64 { 6: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::id($t0: u64): u64 { + var $t1: u64 + 0: $t1 := move($t0) + 1: return $t1 +} + + +[variant baseline] +fun m::test($t0: u64): u64 { + var $t1: u64 + var $t2: u64 [unused] + var $t3: u64 + var $t4: u64 + var $t5: u64 + var $t6: u64 + 0: $t3 := move($t0) + 1: $t4 := move($t3) + 2: $t6 := m::id($t4) + 3: $t5 := m::id($t6) + 4: $t1 := m::id($t5) + 5: return $t1 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -101,6 +127,29 @@ fun m::test($t0: u64): u64 { 5: return $t0 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::id($t0: u64): u64 { + var $t1: u64 [unused] + 0: return $t0 +} + + +[variant baseline] +fun m::test($t0: u64): u64 { + var $t1: u64 [unused] + var $t2: u64 [unused] + var $t3: u64 [unused] + var $t4: u64 [unused] + var $t5: u64 [unused] + var $t6: u64 [unused] + 0: $t0 := m::id($t0) + 1: $t0 := m::id($t0) + 2: $t0 := m::id($t0) + 3: return $t0 +} + ============ disassembled file-format ================== // Move bytecode v7 @@ -114,15 +163,11 @@ B0: } test(Arg0: u64): u64 /* def_idx: 1 */ { B0: - 0: CopyLoc[0](Arg0: u64) + 0: MoveLoc[0](Arg0: u64) 1: Call id(u64): u64 - 2: StLoc[0](Arg0: u64) - 3: CopyLoc[0](Arg0: u64) - 4: Call id(u64): u64 - 5: StLoc[0](Arg0: u64) - 6: CopyLoc[0](Arg0: u64) - 7: Call id(u64): u64 - 8: Ret + 2: Call id(u64): u64 + 3: Call id(u64): u64 + 4: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/call_2.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/call_2.opt.exp index 93cfbdae1d595..d51e981ce065e 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/call_2.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/call_2.opt.exp @@ -25,6 +25,33 @@ fun m::test($t0: u64): u64 { 6: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::update($t0: &mut u64) { + var $t1: u64 + 0: $t1 := 0 + 1: write_ref($t0, $t1) + 2: return () +} + + +[variant baseline] +fun m::test($t0: u64): u64 { + var $t1: u64 + var $t2: u64 + var $t3: u64 + var $t4: u64 + var $t5: &mut u64 + 0: $t2 := copy($t0) + 1: $t3 := move($t0) + 2: $t4 := move($t3) + 3: $t5 := borrow_local($t2) + 4: m::update($t5) + 5: $t1 := move($t4) + 6: return $t1 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -98,6 +125,30 @@ fun m::test($t0: u64): u64 { 6: return $t0 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::update($t0: &mut u64) { + var $t1: u64 + 0: $t1 := 0 + 1: write_ref($t0, $t1) + 2: return () +} + + +[variant baseline] +fun m::test($t0: u64): u64 { + var $t1: u64 [unused] + var $t2: u64 + var $t3: u64 [unused] + var $t4: u64 [unused] + var $t5: &mut u64 + 0: $t2 := copy($t0) + 1: $t5 := borrow_local($t2) + 2: m::update($t5) + 3: return $t0 +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/cant_coalesce_1.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/cant_coalesce_1.opt.exp index 18f22ff8154ed..0421981781a4e 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/cant_coalesce_1.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/cant_coalesce_1.opt.exp @@ -17,6 +17,17 @@ public fun m::test($t0: u64): u64 { 2: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +public fun m::test($t0: u64): u64 { + var $t1: u64 + var $t2: u64 + 0: $t2 := +($t0, $t0) + 1: $t1 := 2 + 2: return $t1 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -45,6 +56,17 @@ public fun m::test($t0: u64): u64 { 2: return $t2 } +============ after DeadStoreElimination: ================ + +[variant baseline] +public fun m::test($t0: u64): u64 { + var $t1: u64 [unused] + var $t2: u64 + 0: $t0 := +($t0, $t0) + 1: $t2 := 2 + 2: return $t2 +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/cant_copy_propagate.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/cant_copy_propagate.opt.exp index 63a623eb6f93d..714466fd830f4 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/cant_copy_propagate.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/cant_copy_propagate.opt.exp @@ -31,6 +31,35 @@ fun m::test($t0: u64, $t1: bool) { 13: return () } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::consume($t0: u64) { + var $t1: u64 [unused] + 0: return () +} + + +[variant baseline] +fun m::test($t0: u64, $t1: bool) { + var $t2: u64 + var $t3: u64 [unused] + var $t4: u64 + var $t5: u64 + var $t6: u64 + 0: $t2 := move($t0) + 1: if ($t1) goto 2 else goto 5 + 2: label L0 + 3: m::consume($t2) + 4: goto 9 + 5: label L1 + 6: $t4 := move($t2) + 7: $t6 := 1 + 8: $t5 := +($t4, $t6) + 9: label L2 + 10: return () +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -107,6 +136,33 @@ fun m::test($t0: u64, $t1: bool) { 10: return () } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::consume($t0: u64) { + var $t1: u64 [unused] + 0: return () +} + + +[variant baseline] +fun m::test($t0: u64, $t1: bool) { + var $t2: u64 [unused] + var $t3: u64 [unused] + var $t4: u64 [unused] + var $t5: u64 [unused] + var $t6: u64 + 0: if ($t1) goto 1 else goto 4 + 1: label L0 + 2: m::consume($t0) + 3: goto 7 + 4: label L1 + 5: $t6 := 1 + 6: $t0 := +($t0, $t6) + 7: label L2 + 8: return () +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/conditional.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/conditional.exp index 055e76461139e..87baa0b16e9c5 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/conditional.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/conditional.exp @@ -156,7 +156,7 @@ B1: B2: 9: LdU64(1) 10: StLoc[3](loc2: u64) - 11: CopyLoc[1](loc0: u64) + 11: MoveLoc[1](loc0: u64) 12: MoveLoc[3](loc2: u64) 13: Add 14: StLoc[2](loc1: u64) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/conditional.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/conditional.opt.exp index 0c0d7cb7e60da..f95ebd998451d 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/conditional.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/conditional.opt.exp @@ -13,6 +13,21 @@ fun m::test($t0: bool): u64 { 7: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test($t0: bool): u64 { + var $t1: u64 + 0: if ($t0) goto 1 else goto 4 + 1: label L0 + 2: $t1 := 3 + 3: goto 6 + 4: label L1 + 5: $t1 := 3 + 6: label L2 + 7: return $t1 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -54,6 +69,21 @@ fun m::test($t0: bool): u64 { 7: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test($t0: bool): u64 { + var $t1: u64 + 0: if ($t0) goto 1 else goto 4 + 1: label L0 + 2: $t1 := 3 + 3: goto 6 + 4: label L1 + 5: $t1 := 3 + 6: label L2 + 7: return $t1 +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_1.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_1.opt.exp index 1c4d7fe90fb44..ab7c97f7a44e7 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_1.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_1.opt.exp @@ -51,6 +51,59 @@ public fun m::test4($t0: m::W) { 3: return () } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::consume($t0: u64) { + 0: return () +} + + +[variant baseline] +fun m::consume_($t0: m::W) { + 0: return () +} + + +[variant baseline] +public fun m::test1($t0: u64) { + var $t1: u64 + 0: $t1 := copy($t0) + 1: m::consume($t0) + 2: m::consume($t1) + 3: return () +} + + +[variant baseline] +public fun m::test2($t0: u64) { + var $t1: u64 + 0: $t1 := copy($t0) + 1: m::consume($t1) + 2: m::consume($t0) + 3: return () +} + + +[variant baseline] +public fun m::test3($t0: m::W) { + var $t1: m::W + 0: $t1 := copy($t0) + 1: m::consume_($t0) + 2: m::consume_($t1) + 3: return () +} + + +[variant baseline] +public fun m::test4($t0: m::W) { + var $t1: m::W + 0: $t1 := copy($t0) + 1: m::consume_($t1) + 2: m::consume_($t0) + 3: return () +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -180,6 +233,59 @@ public fun m::test3($t0: m::W) { } +[variant baseline] +public fun m::test4($t0: m::W) { + var $t1: m::W + 0: $t1 := copy($t0) + 1: m::consume_($t1) + 2: m::consume_($t0) + 3: return () +} + +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::consume($t0: u64) { + 0: return () +} + + +[variant baseline] +fun m::consume_($t0: m::W) { + 0: return () +} + + +[variant baseline] +public fun m::test1($t0: u64) { + var $t1: u64 + 0: $t1 := copy($t0) + 1: m::consume($t0) + 2: m::consume($t1) + 3: return () +} + + +[variant baseline] +public fun m::test2($t0: u64) { + var $t1: u64 + 0: $t1 := copy($t0) + 1: m::consume($t1) + 2: m::consume($t0) + 3: return () +} + + +[variant baseline] +public fun m::test3($t0: m::W) { + var $t1: m::W + 0: $t1 := copy($t0) + 1: m::consume_($t0) + 2: m::consume_($t1) + 3: return () +} + + [variant baseline] public fun m::test4($t0: m::W) { var $t1: m::W diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_2.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_2.opt.exp index ef7efed4e168c..b799b997faf13 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_2.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_2.opt.exp @@ -31,6 +31,41 @@ public fun m::test2($t0: m::W) { 3: return () } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::consume($t0: u64) { + 0: return () +} + + +[variant baseline] +fun m::consume_($t0: m::W) { + 0: return () +} + + +[variant baseline] +public fun m::test1($t0: u64) { + var $t1: u64 + 0: $t1 := move($t0) + 1: m::consume($t1) + 2: m::consume($t1) + 3: return () +} + + +[variant baseline] +public fun m::test2($t0: m::W) { + var $t1: m::W + var $t2: m::W + 0: $t1 := move($t0) + 1: $t2 := copy($t1) + 2: m::consume_($t2) + 3: m::consume_($t1) + 4: return () +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -120,6 +155,39 @@ public fun m::test2($t0: m::W) { 4: return () } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::consume($t0: u64) { + 0: return () +} + + +[variant baseline] +fun m::consume_($t0: m::W) { + 0: return () +} + + +[variant baseline] +public fun m::test1($t0: u64) { + var $t1: u64 [unused] + 0: m::consume($t0) + 1: m::consume($t0) + 2: return () +} + + +[variant baseline] +public fun m::test2($t0: m::W) { + var $t1: m::W [unused] + var $t2: m::W + 0: $t2 := copy($t0) + 1: m::consume_($t2) + 2: m::consume_($t0) + 3: return () +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_3.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_3.opt.exp index 11c7f7a9ab587..65e69a5f90eab 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_3.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_3.opt.exp @@ -22,6 +22,39 @@ public fun m::test($t0: u32) { } +[variant baseline] +public fun m::test_($t0: m::W) { + var $t1: m::W + 0: $t1 := copy($t0) + 1: m::consume_($t1) + 2: m::consume_($t0) + 3: return () +} + +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::consume($t0: u32) { + 0: return () +} + + +[variant baseline] +fun m::consume_($t0: m::W) { + 0: return () +} + + +[variant baseline] +public fun m::test($t0: u32) { + var $t1: u32 + 0: $t1 := copy($t0) + 1: m::consume($t1) + 2: m::consume($t0) + 3: return () +} + + [variant baseline] public fun m::test_($t0: m::W) { var $t1: m::W @@ -106,6 +139,39 @@ public fun m::test($t0: u32) { } +[variant baseline] +public fun m::test_($t0: m::W) { + var $t1: m::W + 0: $t1 := copy($t0) + 1: m::consume_($t1) + 2: m::consume_($t0) + 3: return () +} + +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::consume($t0: u32) { + 0: return () +} + + +[variant baseline] +fun m::consume_($t0: m::W) { + 0: return () +} + + +[variant baseline] +public fun m::test($t0: u32) { + var $t1: u32 + 0: $t1 := copy($t0) + 1: m::consume($t1) + 2: m::consume($t0) + 3: return () +} + + [variant baseline] public fun m::test_($t0: m::W) { var $t1: m::W diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_4.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_4.opt.exp index 603e4d16fbb57..e1ea8e5518654 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_4.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_4.opt.exp @@ -24,6 +24,43 @@ public fun m::test($t0: u32) { } +[variant baseline] +public fun m::test_struct($t0: m::W) { + var $t1: m::W + var $t2: m::W + 0: $t1 := copy($t0) + 1: $t2 := move($t1) + 2: m::consume_($t2) + 3: m::consume_($t0) + 4: return () +} + +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::consume($t0: u32) { + 0: return () +} + + +[variant baseline] +fun m::consume_($t0: m::W) { + 0: return () +} + + +[variant baseline] +public fun m::test($t0: u32) { + var $t1: u32 + var $t2: u32 + 0: $t1 := copy($t0) + 1: $t2 := move($t1) + 2: m::consume($t2) + 3: m::consume($t0) + 4: return () +} + + [variant baseline] public fun m::test_struct($t0: m::W) { var $t1: m::W @@ -131,6 +168,41 @@ public fun m::test_struct($t0: m::W) { 4: return () } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::consume($t0: u32) { + 0: return () +} + + +[variant baseline] +fun m::consume_($t0: m::W) { + 0: return () +} + + +[variant baseline] +public fun m::test($t0: u32) { + var $t1: u32 + var $t2: u32 [unused] + 0: $t1 := copy($t0) + 1: m::consume($t1) + 2: m::consume($t0) + 3: return () +} + + +[variant baseline] +public fun m::test_struct($t0: m::W) { + var $t1: m::W + var $t2: m::W [unused] + 0: $t1 := copy($t0) + 1: m::consume_($t1) + 2: m::consume_($t0) + 3: return () +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_5.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_5.exp index 8bc6b30f92384..5be2286c87db9 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_5.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_5.exp @@ -404,7 +404,7 @@ B2: 7: CopyLoc[1](Arg1: u32) 8: Call consume(u32) B3: - 9: CopyLoc[0](Arg0: bool) + 9: MoveLoc[0](Arg0: bool) 10: Not 11: BrFalse(15) B4: @@ -437,7 +437,7 @@ B2: 11: MoveLoc[3](loc1: W) 12: Call consume_(W) B3: - 13: CopyLoc[0](Arg0: bool) + 13: MoveLoc[0](Arg0: bool) 14: Not 15: BrFalse(19) B4: diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_5.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_5.opt.exp index bafe4c067c255..5be2286c87db9 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_5.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/consume_5.opt.exp @@ -59,6 +59,71 @@ public fun m::test_struct($t0: bool, $t1: m::W) { 16: return () } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::consume($t0: u32) { + 0: return () +} + + +[variant baseline] +fun m::consume_($t0: m::W) { + 0: return () +} + + +[variant baseline] +public fun m::test($t0: bool, $t1: u32) { + var $t2: u32 + var $t3: bool + 0: $t2 := copy($t1) + 1: if ($t0) goto 2 else goto 5 + 2: label L0 + 3: m::consume($t2) + 4: goto 7 + 5: label L1 + 6: m::consume($t1) + 7: label L2 + 8: $t3 := !($t0) + 9: if ($t3) goto 10 else goto 13 + 10: label L3 + 11: m::consume($t1) + 12: goto 15 + 13: label L4 + 14: m::consume($t2) + 15: label L5 + 16: return () +} + + +[variant baseline] +public fun m::test_struct($t0: bool, $t1: m::W) { + var $t2: m::W + var $t3: bool + var $t4: m::W + var $t5: m::W + 0: $t2 := copy($t1) + 1: if ($t0) goto 2 else goto 6 + 2: label L0 + 3: $t4 := copy($t2) + 4: m::consume_($t4) + 5: goto 9 + 6: label L1 + 7: $t5 := copy($t1) + 8: m::consume_($t5) + 9: label L2 + 10: $t3 := !($t0) + 11: if ($t3) goto 12 else goto 15 + 12: label L3 + 13: m::consume_($t1) + 14: goto 17 + 15: label L4 + 16: m::consume_($t2) + 17: label L5 + 18: return () +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -216,6 +281,71 @@ public fun m::test($t0: bool, $t1: u32) { } +[variant baseline] +public fun m::test_struct($t0: bool, $t1: m::W) { + var $t2: m::W + var $t3: bool [unused] + var $t4: m::W + var $t5: m::W [unused] + 0: $t2 := copy($t1) + 1: if ($t0) goto 2 else goto 6 + 2: label L0 + 3: $t4 := copy($t2) + 4: m::consume_($t4) + 5: goto 9 + 6: label L1 + 7: $t4 := copy($t1) + 8: m::consume_($t4) + 9: label L2 + 10: $t0 := !($t0) + 11: if ($t0) goto 12 else goto 15 + 12: label L3 + 13: m::consume_($t1) + 14: goto 17 + 15: label L4 + 16: m::consume_($t2) + 17: label L5 + 18: return () +} + +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::consume($t0: u32) { + 0: return () +} + + +[variant baseline] +fun m::consume_($t0: m::W) { + 0: return () +} + + +[variant baseline] +public fun m::test($t0: bool, $t1: u32) { + var $t2: u32 + var $t3: bool [unused] + 0: $t2 := copy($t1) + 1: if ($t0) goto 2 else goto 5 + 2: label L0 + 3: m::consume($t2) + 4: goto 7 + 5: label L1 + 6: m::consume($t1) + 7: label L2 + 8: $t0 := !($t0) + 9: if ($t0) goto 10 else goto 13 + 10: label L3 + 11: m::consume($t1) + 12: goto 15 + 13: label L4 + 14: m::consume($t2) + 15: label L5 + 16: return () +} + + [variant baseline] public fun m::test_struct($t0: bool, $t1: m::W) { var $t2: m::W @@ -274,7 +404,7 @@ B2: 7: CopyLoc[1](Arg1: u32) 8: Call consume(u32) B3: - 9: CopyLoc[0](Arg0: bool) + 9: MoveLoc[0](Arg0: bool) 10: Not 11: BrFalse(15) B4: @@ -307,7 +437,7 @@ B2: 11: MoveLoc[3](loc1: W) 12: Call consume_(W) B3: - 13: CopyLoc[0](Arg0: bool) + 13: MoveLoc[0](Arg0: bool) 14: Not 15: BrFalse(19) B4: diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_assignment_without_use.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_assignment_without_use.opt.exp index ca621426b8dbf..1be5d8b6fc8ed 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_assignment_without_use.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_assignment_without_use.opt.exp @@ -12,6 +12,16 @@ public fun m::test($t0: u64) { 4: return () } +============ after DeadStoreElimination: ================ + +[variant baseline] +public fun m::test($t0: u64) { + var $t1: u64 [unused] + var $t2: u64 [unused] + var $t3: u64 [unused] + 0: return () +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -34,6 +44,16 @@ public fun m::test($t0: u64) { 0: return () } +============ after DeadStoreElimination: ================ + +[variant baseline] +public fun m::test($t0: u64) { + var $t1: u64 [unused] + var $t2: u64 [unused] + var $t3: u64 [unused] + 0: return () +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_assignments.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_assignments.opt.exp index 2105f5c48224a..e7bb1111ab30a 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_assignments.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_assignments.opt.exp @@ -12,6 +12,20 @@ fun m::cyclic($t0: u64): u64 { 4: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::cyclic($t0: u64): u64 { + var $t1: u64 + var $t2: u64 + var $t3: u64 + 0: $t2 := move($t0) + 1: $t3 := move($t2) + 2: $t0 := move($t3) + 3: $t1 := move($t0) + 4: return $t1 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -50,6 +64,18 @@ fun m::cyclic($t0: u64): u64 { 4: return $t0 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::cyclic($t0: u64): u64 { + var $t1: u64 [unused] + var $t2: u64 + var $t3: u64 [unused] + 0: $t2 := move($t0) + 1: $t0 := move($t2) + 2: return $t0 +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_dead_store.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_dead_store.exp index c7f9907af1921..467e6fdde809e 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_dead_store.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_dead_store.exp @@ -325,7 +325,7 @@ B2: 10: LdU64(1) 11: StLoc[1](Arg1: u64) 12: MoveLoc[3](loc0: u64) - 13: CopyLoc[1](Arg1: u64) + 13: MoveLoc[1](Arg1: u64) 14: Add 15: StLoc[3](loc0: u64) 16: Branch(18) @@ -350,7 +350,7 @@ B2: 6: LdU64(1) 7: StLoc[2](loc0: u64) 8: MoveLoc[1](Arg1: u64) - 9: CopyLoc[2](loc0: u64) + 9: MoveLoc[2](loc0: u64) 10: Add 11: StLoc[1](Arg1: u64) 12: Branch(14) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_dead_store.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_dead_store.opt.exp index 1c6e755d26efc..467e6fdde809e 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_dead_store.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/cyclic_dead_store.opt.exp @@ -50,6 +50,57 @@ public fun m::test2($t0: u64, $t1: u64) { 15: return () } +============ after DeadStoreElimination: ================ + +[variant baseline] +public fun m::test1($t0: u64, $t1: u64, $t2: u64) { + var $t3: u64 + var $t4: bool + var $t5: u64 + var $t6: u64 + 0: $t3 := 0 + 1: label L0 + 2: $t4 := <($t3, $t0) + 3: if ($t4) goto 4 else goto 11 + 4: label L2 + 5: $t1 := move($t2) + 6: $t2 := move($t1) + 7: $t6 := 1 + 8: $t5 := +($t3, $t6) + 9: $t3 := move($t5) + 10: goto 13 + 11: label L3 + 12: goto 15 + 13: label L4 + 14: goto 1 + 15: label L1 + 16: return () +} + + +[variant baseline] +public fun m::test2($t0: u64, $t1: u64) { + var $t2: u64 + var $t3: bool + var $t4: u64 + var $t5: u64 + 0: $t2 := 0 + 1: label L0 + 2: $t3 := <($t2, $t0) + 3: if ($t3) goto 4 else goto 9 + 4: label L2 + 5: $t5 := 1 + 6: $t4 := +($t2, $t5) + 7: $t2 := move($t4) + 8: goto 11 + 9: label L3 + 10: goto 13 + 11: label L4 + 12: goto 1 + 13: label L1 + 14: return () +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -176,6 +227,57 @@ public fun m::test1($t0: u64, $t1: u64, $t2: u64) { } +[variant baseline] +public fun m::test2($t0: u64, $t1: u64) { + var $t2: u64 [unused] + var $t3: bool + var $t4: u64 [unused] + var $t5: u64 + 0: $t1 := 0 + 1: label L0 + 2: $t3 := <($t1, $t0) + 3: if ($t3) goto 4 else goto 9 + 4: label L2 + 5: $t5 := 1 + 6: $t5 := +($t1, $t5) + 7: $t1 := move($t5) + 8: goto 11 + 9: label L3 + 10: goto 13 + 11: label L4 + 12: goto 1 + 13: label L1 + 14: return () +} + +============ after DeadStoreElimination: ================ + +[variant baseline] +public fun m::test1($t0: u64, $t1: u64, $t2: u64) { + var $t3: u64 + var $t4: bool + var $t5: u64 [unused] + var $t6: u64 [unused] + 0: $t3 := 0 + 1: label L0 + 2: $t4 := <($t3, $t0) + 3: if ($t4) goto 4 else goto 11 + 4: label L2 + 5: $t1 := move($t2) + 6: $t2 := move($t1) + 7: $t1 := 1 + 8: $t1 := +($t3, $t1) + 9: $t3 := move($t1) + 10: goto 13 + 11: label L3 + 12: goto 15 + 13: label L4 + 14: goto 1 + 15: label L1 + 16: return () +} + + [variant baseline] public fun m::test2($t0: u64, $t1: u64) { var $t2: u64 [unused] @@ -223,7 +325,7 @@ B2: 10: LdU64(1) 11: StLoc[1](Arg1: u64) 12: MoveLoc[3](loc0: u64) - 13: CopyLoc[1](Arg1: u64) + 13: MoveLoc[1](Arg1: u64) 14: Add 15: StLoc[3](loc0: u64) 16: Branch(18) @@ -248,7 +350,7 @@ B2: 6: LdU64(1) 7: StLoc[2](loc0: u64) 8: MoveLoc[1](Arg1: u64) - 9: CopyLoc[2](loc0: u64) + 9: MoveLoc[2](loc0: u64) 10: Add 11: StLoc[1](Arg1: u64) 12: Branch(14) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_1.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_1.opt.exp index c1c6419ce95a0..2cc99f49b4eab 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_1.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_1.opt.exp @@ -11,6 +11,19 @@ fun m::dead($t0: u64): u64 { 3: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::dead($t0: u64): u64 { + var $t1: u64 + var $t2: u64 + var $t3: u64 + 0: $t2 := move($t0) + 1: $t3 := move($t2) + 2: $t1 := move($t3) + 3: return $t1 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -45,6 +58,16 @@ fun m::dead($t0: u64): u64 { 3: return $t0 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::dead($t0: u64): u64 { + var $t1: u64 [unused] + var $t2: u64 [unused] + var $t3: u64 [unused] + 0: return $t0 +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_2.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_2.opt.exp index cfdf081b7f035..ff4216c1abb91 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_2.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_2.opt.exp @@ -8,6 +8,15 @@ fun m::dead($t0: u64): u64 { 2: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::dead($t0: u64): u64 { + var $t1: u64 + 0: $t1 := move($t0) + 1: return $t1 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -30,6 +39,14 @@ fun m::dead($t0: u64): u64 { 1: return $t0 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::dead($t0: u64): u64 { + var $t1: u64 [unused] + 0: return $t0 +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_3.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_3.opt.exp index f5c119afc82a0..10501d30e9943 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_3.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_3.opt.exp @@ -18,6 +18,23 @@ public fun m::test($t0: bool): u32 { 11: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +public fun m::test($t0: bool): u32 { + var $t1: u32 + var $t2: u32 + 0: $t2 := 1 + 1: if ($t0) goto 2 else goto 5 + 2: label L0 + 3: $t1 := move($t2) + 4: goto 7 + 5: label L1 + 6: $t1 := 9 + 7: label L2 + 8: return $t1 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -66,6 +83,23 @@ public fun m::test($t0: bool): u32 { 8: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +public fun m::test($t0: bool): u32 { + var $t1: u32 + var $t2: u32 + 0: $t2 := 1 + 1: if ($t0) goto 2 else goto 5 + 2: label L0 + 3: $t1 := move($t2) + 4: goto 7 + 5: label L1 + 6: $t1 := 9 + 7: label L2 + 8: return $t1 +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_4.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_4.opt.exp index ddde90c8e1e79..6a523fee558e2 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_4.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/dead_assignment_4.opt.exp @@ -54,6 +54,41 @@ public fun m::test3($t0: u64): u64 { } +[variant baseline] +public fun m::test4($t0: u64): u64 { + var $t1: u64 + 0: $t1 := 1 + 1: return $t1 +} + +============ after DeadStoreElimination: ================ + +[variant baseline] +public fun m::test1(): u64 { + var $t0: u64 + 0: $t0 := 3 + 1: return $t0 +} + + +[variant baseline] +public fun m::test2($t0: u64): u64 { + var $t1: u64 + var $t2: u64 [unused] + 0: $t1 := move($t0) + 1: return $t1 +} + + +[variant baseline] +public fun m::test3($t0: u64): u64 { + var $t1: u64 + var $t2: u64 [unused] + 0: $t1 := 8 + 1: return $t1 +} + + [variant baseline] public fun m::test4($t0: u64): u64 { var $t1: u64 @@ -140,6 +175,40 @@ public fun m::test3($t0: u64): u64 { } +[variant baseline] +public fun m::test4($t0: u64): u64 { + var $t1: u64 [unused] + 0: $t0 := 1 + 1: return $t0 +} + +============ after DeadStoreElimination: ================ + +[variant baseline] +public fun m::test1(): u64 { + var $t0: u64 + 0: $t0 := 3 + 1: return $t0 +} + + +[variant baseline] +public fun m::test2($t0: u64): u64 { + var $t1: u64 [unused] + var $t2: u64 [unused] + 0: return $t0 +} + + +[variant baseline] +public fun m::test3($t0: u64): u64 { + var $t1: u64 [unused] + var $t2: u64 [unused] + 0: $t0 := 8 + 1: return $t0 +} + + [variant baseline] public fun m::test4($t0: u64): u64 { var $t1: u64 [unused] diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/immut_refs_1.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/immut_refs_1.opt.exp index fd1304c12ac18..117db0d49b65d 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/immut_refs_1.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/immut_refs_1.opt.exp @@ -13,6 +13,21 @@ fun m::test($t0: u64): u64 { 4: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test($t0: u64): u64 { + var $t1: u64 + var $t2: &u64 + var $t3: &u64 + var $t4: &u64 + 0: $t2 := borrow_local($t0) + 1: $t3 := move($t2) + 2: $t4 := move($t3) + 3: $t1 := read_ref($t4) + 4: return $t1 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -53,6 +68,19 @@ fun m::test($t0: u64): u64 { 4: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test($t0: u64): u64 { + var $t1: u64 + var $t2: &u64 + var $t3: &u64 [unused] + var $t4: &u64 [unused] + 0: $t2 := borrow_local($t0) + 1: $t1 := read_ref($t2) + 2: return $t1 +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/immut_refs_2.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/immut_refs_2.opt.exp index 446524618b5cf..aef9456582cdc 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/immut_refs_2.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/immut_refs_2.opt.exp @@ -23,6 +23,24 @@ fun m::test($t0: u64): u64 { 5: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test($t0: u64): u64 { + var $t1: u64 + var $t2: &u64 + var $t3: u64 + var $t4: u64 + var $t5: u64 + 0: $t2 := borrow_local($t0) + 1: drop($t2) + 2: $t3 := move($t0) + 3: $t4 := move($t3) + 4: $t5 := move($t4) + 5: $t1 := move($t5) + 6: return $t1 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -73,6 +91,21 @@ fun m::test($t0: u64): u64 { 6: return $t3 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test($t0: u64): u64 { + var $t1: u64 [unused] + var $t2: &u64 + var $t3: u64 + var $t4: u64 [unused] + var $t5: u64 [unused] + 0: $t2 := borrow_local($t0) + 1: drop($t2) + 2: $t3 := move($t0) + 3: return $t3 +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/inlining1.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/inlining1.opt.exp index c9de650ba38ac..fdf29d55e2bf7 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/inlining1.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/inlining1.opt.exp @@ -7,6 +7,15 @@ public fun Test::test(): u64 { 1: return $t0 } +============ after DeadStoreElimination: ================ + +[variant baseline] +public fun Test::test(): u64 { + var $t0: u64 + 0: $t0 := 3 + 1: return $t0 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -29,6 +38,15 @@ public fun Test::test(): u64 { 1: return $t0 } +============ after DeadStoreElimination: ================ + +[variant baseline] +public fun Test::test(): u64 { + var $t0: u64 + 0: $t0 := 3 + 1: return $t0 +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_1.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_1.exp index 46b312d1a9e8d..8ad92bf681375 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_1.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_1.exp @@ -114,7 +114,7 @@ B0: 5: CopyLoc[0](loc0: u64) 6: StLoc[1](loc1: u64) 7: MoveLoc[1](loc1: u64) - 8: CopyLoc[0](loc0: u64) + 8: MoveLoc[0](loc0: u64) 9: Add 10: StLoc[0](loc0: u64) 11: Pop diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_1.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_1.opt.exp index 487505f544dcf..c8d8e9c9ea66b 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_1.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_1.opt.exp @@ -14,6 +14,21 @@ fun m::test(): u64 { 5: return $t0 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test(): u64 { + var $t0: u64 + var $t1: u64 + var $t2: u64 + var $t3: u64 + 0: $t1 := 1 + 1: $t3 := 2 + 2: $t2 := +($t1, $t3) + 3: $t0 := 4 + 4: return $t0 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -54,6 +69,21 @@ fun m::test(): u64 { 4: return $t2 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test(): u64 { + var $t0: u64 [unused] + var $t1: u64 + var $t2: u64 + var $t3: u64 + 0: $t1 := 1 + 1: $t3 := 2 + 2: $t1 := +($t1, $t3) + 3: $t2 := 4 + 4: return $t2 +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_2.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_2.exp index 5e9014a00b934..675e4b1a4960c 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_2.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_2.exp @@ -131,11 +131,11 @@ B0: 4: StLoc[1](loc1: u64) 5: StLoc[2](loc2: u64) 6: MoveLoc[2](loc2: u64) - 7: CopyLoc[0](loc0: u64) + 7: MoveLoc[0](loc0: u64) 8: Add 9: StLoc[2](loc2: u64) 10: MoveLoc[1](loc1: u64) - 11: CopyLoc[2](loc2: u64) + 11: MoveLoc[2](loc2: u64) 12: Add 13: Ret } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_2.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_2.opt.exp index 0d43fb1592c18..def8e4b7b85f5 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_2.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_2.opt.exp @@ -16,6 +16,24 @@ fun m::test(): u64 { 6: return $t0 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test(): u64 { + var $t0: u64 + var $t1: u64 + var $t2: u64 + var $t3: u64 + var $t4: u64 + 0: $t1 := 1 + 1: $t3 := 1 + 2: $t2 := +($t1, $t3) + 3: $t1 := move($t2) + 4: $t4 := 2 + 5: $t0 := +($t4, $t1) + 6: return $t0 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -66,6 +84,24 @@ fun m::test(): u64 { 6: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test(): u64 { + var $t0: u64 [unused] + var $t1: u64 + var $t2: u64 [unused] + var $t3: u64 + var $t4: u64 [unused] + 0: $t1 := 1 + 1: $t3 := 1 + 2: $t3 := +($t1, $t3) + 3: $t1 := move($t3) + 4: $t3 := 2 + 5: $t1 := +($t3, $t1) + 6: return $t1 +} + ============ disassembled file-format ================== // Move bytecode v7 @@ -74,18 +110,15 @@ module c0ffee.m { test(): u64 /* def_idx: 0 */ { L0: loc0: u64 -L1: loc1: u64 B0: 0: LdU64(1) 1: LdU64(1) - 2: StLoc[0](loc0: u64) - 3: CopyLoc[0](loc0: u64) - 4: Add - 5: StLoc[1](loc1: u64) - 6: LdU64(2) - 7: CopyLoc[1](loc1: u64) - 8: Add - 9: Ret + 2: Add + 3: StLoc[0](loc0: u64) + 4: LdU64(2) + 5: MoveLoc[0](loc0: u64) + 6: Add + 7: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_3.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_3.opt.exp index 98fffff80a033..dd35312daf6a4 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_3.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/intermingled_3.opt.exp @@ -14,6 +14,21 @@ fun m::test(): u64 { 5: return $t0 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test(): u64 { + var $t0: u64 + var $t1: u64 + var $t2: u64 + var $t3: u64 + 0: $t1 := 1 + 1: $t3 := 1 + 2: $t2 := +($t1, $t3) + 3: $t0 := 2 + 4: return $t0 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -54,6 +69,21 @@ fun m::test(): u64 { 4: return $t2 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test(): u64 { + var $t0: u64 [unused] + var $t1: u64 + var $t2: u64 + var $t3: u64 + 0: $t1 := 1 + 1: $t3 := 1 + 2: $t1 := +($t1, $t3) + 3: $t2 := 2 + 4: return $t2 +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_1.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_1.exp index 0265fb2587d7a..d483a330b93f6 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_1.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_1.exp @@ -215,7 +215,7 @@ B2: 12: LdU64(1) 13: StLoc[3](loc2: u64) 14: MoveLoc[1](loc0: u64) - 15: CopyLoc[3](loc2: u64) + 15: MoveLoc[3](loc2: u64) 16: Add 17: StLoc[1](loc0: u64) 18: Branch(20) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_1.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_1.opt.exp index d848f6885925c..d483a330b93f6 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_1.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_1.opt.exp @@ -30,6 +30,38 @@ fun m::test($t0: u64): u64 { 18: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test($t0: u64): u64 { + var $t1: u64 + var $t2: u64 + var $t3: u64 + var $t4: bool + var $t5: u64 + var $t6: u64 + var $t7: u64 + 0: $t2 := 0 + 1: $t3 := 0 + 2: label L0 + 3: $t5 := 10 + 4: $t4 := <($t3, $t5) + 5: if ($t4) goto 6 else goto 12 + 6: label L2 + 7: $t2 := copy($t0) + 8: $t7 := 1 + 9: $t6 := +($t3, $t7) + 10: $t3 := move($t6) + 11: goto 14 + 12: label L3 + 13: goto 16 + 14: label L4 + 15: goto 2 + 16: label L1 + 17: $t1 := move($t2) + 18: return $t1 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -124,6 +156,37 @@ fun m::test($t0: u64): u64 { 18: return $t2 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test($t0: u64): u64 { + var $t1: u64 [unused] + var $t2: u64 + var $t3: u64 + var $t4: bool + var $t5: u64 + var $t6: u64 [unused] + var $t7: u64 [unused] + 0: $t2 := 0 + 1: $t3 := 0 + 2: label L0 + 3: $t5 := 10 + 4: $t4 := <($t3, $t5) + 5: if ($t4) goto 6 else goto 12 + 6: label L2 + 7: $t2 := copy($t0) + 8: $t5 := 1 + 9: $t5 := +($t3, $t5) + 10: $t3 := move($t5) + 11: goto 14 + 12: label L3 + 13: goto 16 + 14: label L4 + 15: goto 2 + 16: label L1 + 17: return $t2 +} + ============ disassembled file-format ================== // Move bytecode v7 @@ -152,7 +215,7 @@ B2: 12: LdU64(1) 13: StLoc[3](loc2: u64) 14: MoveLoc[1](loc0: u64) - 15: CopyLoc[3](loc2: u64) + 15: MoveLoc[3](loc2: u64) 16: Add 17: StLoc[1](loc0: u64) 18: Branch(20) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_2.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_2.exp index b00bffcabbc6f..2e9f50fb4673f 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_2.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_2.exp @@ -215,7 +215,7 @@ B2: 12: LdU64(1) 13: StLoc[3](loc2: u64) 14: MoveLoc[2](loc1: u64) - 15: CopyLoc[3](loc2: u64) + 15: MoveLoc[3](loc2: u64) 16: Add 17: StLoc[2](loc1: u64) 18: Branch(20) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_2.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_2.opt.exp index f8eaf1534c1fb..2e9f50fb4673f 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_2.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/loop_2.opt.exp @@ -30,6 +30,38 @@ fun m::test($t0: u64): u64 { 18: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test($t0: u64): u64 { + var $t1: u64 + var $t2: u64 + var $t3: u64 + var $t4: bool + var $t5: u64 + var $t6: u64 + var $t7: u64 + 0: $t2 := copy($t0) + 1: $t3 := 0 + 2: label L0 + 3: $t5 := 10 + 4: $t4 := <($t3, $t5) + 5: if ($t4) goto 6 else goto 12 + 6: label L2 + 7: $t2 := copy($t0) + 8: $t7 := 1 + 9: $t6 := +($t3, $t7) + 10: $t3 := move($t6) + 11: goto 14 + 12: label L3 + 13: goto 16 + 14: label L4 + 15: goto 2 + 16: label L1 + 17: $t1 := move($t2) + 18: return $t1 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -124,6 +156,37 @@ fun m::test($t0: u64): u64 { 18: return $t2 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test($t0: u64): u64 { + var $t1: u64 [unused] + var $t2: u64 + var $t3: u64 + var $t4: bool + var $t5: u64 + var $t6: u64 [unused] + var $t7: u64 [unused] + 0: $t2 := copy($t0) + 1: $t3 := 0 + 2: label L0 + 3: $t5 := 10 + 4: $t4 := <($t3, $t5) + 5: if ($t4) goto 6 else goto 12 + 6: label L2 + 7: $t2 := copy($t0) + 8: $t5 := 1 + 9: $t5 := +($t3, $t5) + 10: $t3 := move($t5) + 11: goto 14 + 12: label L3 + 13: goto 16 + 14: label L4 + 15: goto 2 + 16: label L1 + 17: return $t2 +} + ============ disassembled file-format ================== // Move bytecode v7 @@ -152,7 +215,7 @@ B2: 12: LdU64(1) 13: StLoc[3](loc2: u64) 14: MoveLoc[2](loc1: u64) - 15: CopyLoc[3](loc2: u64) + 15: MoveLoc[3](loc2: u64) 16: Add 17: StLoc[2](loc1: u64) 18: Branch(20) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/multi_assigns.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/multi_assigns.opt.exp index 33ec89f3c1440..487f77be960ef 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/multi_assigns.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/multi_assigns.opt.exp @@ -12,6 +12,19 @@ fun m::test(): u64 { 4: return $t0 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test(): u64 { + var $t0: u64 + var $t1: u64 + var $t2: u64 + 0: $t2 := 2 + 1: $t1 := move($t2) + 2: $t0 := move($t1) + 3: return $t0 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -46,6 +59,17 @@ fun m::test(): u64 { 3: return $t2 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test(): u64 { + var $t0: u64 [unused] + var $t1: u64 [unused] + var $t2: u64 + 0: $t2 := 2 + 1: return $t2 +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/mut_refs_1.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/mut_refs_1.opt.exp index 245da275c4e78..48c4835a4f88f 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/mut_refs_1.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/mut_refs_1.opt.exp @@ -14,6 +14,22 @@ fun m::test($t0: u64): u64 { 5: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test($t0: u64): u64 { + var $t1: u64 + var $t2: u64 + var $t3: &mut u64 + var $t4: u64 + 0: $t2 := copy($t0) + 1: $t3 := borrow_local($t0) + 2: $t4 := 1 + 3: write_ref($t3, $t4) + 4: $t1 := move($t2) + 5: return $t1 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -58,6 +74,21 @@ fun m::test($t0: u64): u64 { 5: return $t2 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test($t0: u64): u64 { + var $t1: u64 [unused] + var $t2: u64 + var $t3: &mut u64 + var $t4: u64 + 0: $t2 := copy($t0) + 1: $t3 := borrow_local($t0) + 2: $t4 := 1 + 3: write_ref($t3, $t4) + 4: return $t2 +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/mut_refs_2.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/mut_refs_2.opt.exp index 48e52bfa2a283..65c94aa2ef855 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/mut_refs_2.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/mut_refs_2.opt.exp @@ -22,6 +22,30 @@ fun m::test($t0: m::S): u64 { 9: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test($t0: m::S): u64 { + var $t1: u64 + var $t2: m::S + var $t3: m::S + var $t4: &mut u64 + var $t5: &mut m::S + var $t6: u64 + var $t7: &m::S + var $t8: &u64 + 0: $t2 := move($t0) + 1: $t3 := copy($t2) + 2: $t5 := borrow_local($t2) + 3: $t4 := borrow_field.a($t5) + 4: $t6 := 0 + 5: write_ref($t4, $t6) + 6: $t7 := borrow_local($t3) + 7: $t8 := borrow_field.a($t7) + 8: $t1 := read_ref($t8) + 9: return $t1 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -89,6 +113,30 @@ fun m::test($t0: m::S): u64 { 9: return $t6 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test($t0: m::S): u64 { + var $t1: u64 [unused] + var $t2: m::S + var $t3: m::S + var $t4: &mut u64 + var $t5: &mut m::S + var $t6: u64 + var $t7: &m::S + var $t8: &u64 + 0: $t2 := move($t0) + 1: $t3 := copy($t2) + 2: $t5 := borrow_local($t2) + 3: $t4 := borrow_field.a($t5) + 4: $t6 := 0 + 5: write_ref($t4, $t6) + 6: $t7 := borrow_local($t3) + 7: $t8 := borrow_field.a($t7) + 8: $t6 := read_ref($t8) + 9: return $t6 +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/non_overlapping_vars1.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/non_overlapping_vars1.opt.exp index d07fc004c7832..754941c708880 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/non_overlapping_vars1.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/non_overlapping_vars1.opt.exp @@ -19,6 +19,25 @@ fun m::test() { 8: return () } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test() { + var $t0: u64 + var $t1: u64 + var $t2: u64 + var $t3: u64 + var $t4: u64 + var $t5: u64 + 0: $t0 := 1 + 1: $t2 := 1 + 2: $t1 := +($t0, $t2) + 3: $t3 := 2 + 4: $t5 := 1 + 5: $t4 := +($t3, $t5) + 6: return () +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -70,6 +89,25 @@ fun m::test() { 6: return () } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test() { + var $t0: u64 + var $t1: u64 + var $t2: u64 + var $t3: u64 [unused] + var $t4: u64 [unused] + var $t5: u64 [unused] + 0: $t0 := 1 + 1: $t2 := 1 + 2: $t0 := +($t0, $t2) + 3: $t1 := 2 + 4: $t2 := 1 + 5: $t1 := +($t1, $t2) + 6: return () +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/non_overlapping_vars_diff_type.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/non_overlapping_vars_diff_type.opt.exp index 7cff08b6f0408..b7f839ff0a194 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/non_overlapping_vars_diff_type.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/non_overlapping_vars_diff_type.opt.exp @@ -19,6 +19,25 @@ fun m::test() { 8: return () } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test() { + var $t0: u32 + var $t1: u32 + var $t2: u32 + var $t3: u64 + var $t4: u64 + var $t5: u64 + 0: $t0 := 1 + 1: $t2 := 1 + 2: $t1 := +($t0, $t2) + 3: $t3 := 2 + 4: $t5 := 1 + 5: $t4 := +($t3, $t5) + 6: return () +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -70,6 +89,25 @@ fun m::test() { 6: return () } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test() { + var $t0: u32 + var $t1: u32 [unused] + var $t2: u32 + var $t3: u64 + var $t4: u64 [unused] + var $t5: u64 + 0: $t0 := 1 + 1: $t2 := 1 + 2: $t0 := +($t0, $t2) + 3: $t3 := 2 + 4: $t5 := 1 + 5: $t3 := +($t3, $t5) + 6: return () +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/overlapping_vars.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/overlapping_vars.exp index f24bb39a3ea4e..4ce45efbf53dd 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/overlapping_vars.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/overlapping_vars.exp @@ -112,14 +112,12 @@ B0: 3: StLoc[0](loc0: u64) 4: StLoc[1](loc1: u64) 5: StLoc[2](loc2: u64) - 6: CopyLoc[2](loc2: u64) + 6: MoveLoc[2](loc2: u64) 7: MoveLoc[1](loc1: u64) 8: Add - 9: StLoc[2](loc2: u64) - 10: CopyLoc[2](loc2: u64) - 11: MoveLoc[0](loc0: u64) - 12: Add - 13: Ret + 9: MoveLoc[0](loc0: u64) + 10: Add + 11: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/overlapping_vars.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/overlapping_vars.opt.exp index 1f20cc68037ee..7453d91177e4f 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/overlapping_vars.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/overlapping_vars.opt.exp @@ -7,6 +7,15 @@ fun m::test(): u64 { 1: return $t0 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test(): u64 { + var $t0: u64 + 0: $t0 := 6 + 1: return $t0 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -29,6 +38,15 @@ fun m::test(): u64 { 1: return $t0 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test(): u64 { + var $t0: u64 + 0: $t0 := 6 + 1: return $t0 +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/reassigned_var.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/reassigned_var.exp index 1045304776f84..5a165b49ca4ca 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/reassigned_var.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/reassigned_var.exp @@ -98,7 +98,7 @@ B0: 2: StLoc[0](loc0: u64) 3: StLoc[1](loc1: u64) 4: MoveLoc[0](loc0: u64) - 5: CopyLoc[1](loc1: u64) + 5: MoveLoc[1](loc1: u64) 6: Add 7: Ret } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/reassigned_var.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/reassigned_var.opt.exp index 660672c033dbd..23428eb311af1 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/reassigned_var.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/reassigned_var.opt.exp @@ -14,6 +14,21 @@ fun m::test(): u64 { 5: return $t0 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test(): u64 { + var $t0: u64 + var $t1: u64 + var $t2: u64 + var $t3: u64 + 0: $t2 := 9 + 1: $t1 := move($t2) + 2: $t3 := 2 + 3: $t0 := +($t1, $t3) + 4: return $t0 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -54,6 +69,20 @@ fun m::test(): u64 { 4: return $t2 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test(): u64 { + var $t0: u64 [unused] + var $t1: u64 [unused] + var $t2: u64 + var $t3: u64 + 0: $t2 := 9 + 1: $t3 := 2 + 2: $t2 := +($t2, $t3) + 3: return $t2 +} + ============ disassembled file-format ================== // Move bytecode v7 @@ -61,17 +90,11 @@ module c0ffee.m { test(): u64 /* def_idx: 0 */ { -L0: loc0: u64 -L1: loc1: u64 B0: 0: LdU64(9) 1: LdU64(2) - 2: StLoc[0](loc0: u64) - 3: StLoc[1](loc1: u64) - 4: CopyLoc[1](loc1: u64) - 5: MoveLoc[0](loc0: u64) - 6: Add - 7: Ret + 2: Add + 3: Ret } } ============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/self_assigns.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/self_assigns.exp index 9382e019f9b62..22650ed85bc01 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/self_assigns.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/self_assigns.exp @@ -461,7 +461,7 @@ B2: 10: LdU64(1) 11: StLoc[2](loc2: u64) 12: MoveLoc[1](loc1: u64) - 13: CopyLoc[2](loc2: u64) + 13: MoveLoc[2](loc2: u64) 14: Add 15: StLoc[1](loc1: u64) 16: Branch(18) @@ -490,7 +490,7 @@ B2: 8: LdU64(1) 9: StLoc[2](loc1: u64) 10: MoveLoc[1](loc0: u64) - 11: CopyLoc[2](loc1: u64) + 11: MoveLoc[2](loc1: u64) 12: Add 13: StLoc[1](loc0: u64) 14: Branch(16) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/self_assigns.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/self_assigns.opt.exp index bd29cfb8725b7..22650ed85bc01 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/self_assigns.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/self_assigns.opt.exp @@ -75,6 +75,79 @@ public fun m::test4($t0: u64): u64 { 17: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +public fun m::test1($t0: u64) { + 0: return () +} + + +[variant baseline] +public fun m::test2($t0: u64): u64 { + var $t1: u64 + 0: $t1 := move($t0) + 1: return $t1 +} + + +[variant baseline] +public fun m::test3(): u64 { + var $t0: u64 + var $t1: u64 + var $t2: u64 + var $t3: bool + var $t4: u64 + var $t5: u64 + var $t6: u64 + 0: $t1 := 0 + 1: $t2 := 1 + 2: label L0 + 3: $t4 := 42 + 4: $t3 := <($t1, $t4) + 5: if ($t3) goto 6 else goto 11 + 6: label L2 + 7: $t6 := 1 + 8: $t5 := +($t1, $t6) + 9: $t1 := move($t5) + 10: goto 13 + 11: label L3 + 12: goto 15 + 13: label L4 + 14: goto 2 + 15: label L1 + 16: $t0 := move($t2) + 17: return $t0 +} + + +[variant baseline] +public fun m::test4($t0: u64): u64 { + var $t1: u64 + var $t2: u64 + var $t3: bool + var $t4: u64 + var $t5: u64 + var $t6: u64 + 0: $t2 := 0 + 1: label L0 + 2: $t4 := 42 + 3: $t3 := <($t2, $t4) + 4: if ($t3) goto 5 else goto 10 + 5: label L2 + 6: $t6 := 1 + 7: $t5 := +($t2, $t6) + 8: $t2 := move($t5) + 9: goto 12 + 10: label L3 + 11: goto 14 + 12: label L4 + 13: goto 1 + 14: label L1 + 15: $t1 := move($t0) + 16: return $t1 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -283,6 +356,76 @@ public fun m::test4($t0: u64): u64 { 16: return $t0 } +============ after DeadStoreElimination: ================ + +[variant baseline] +public fun m::test1($t0: u64) { + 0: return () +} + + +[variant baseline] +public fun m::test2($t0: u64): u64 { + var $t1: u64 [unused] + 0: return $t0 +} + + +[variant baseline] +public fun m::test3(): u64 { + var $t0: u64 [unused] + var $t1: u64 + var $t2: u64 + var $t3: bool + var $t4: u64 + var $t5: u64 [unused] + var $t6: u64 [unused] + 0: $t1 := 0 + 1: $t2 := 1 + 2: label L0 + 3: $t4 := 42 + 4: $t3 := <($t1, $t4) + 5: if ($t3) goto 6 else goto 11 + 6: label L2 + 7: $t4 := 1 + 8: $t4 := +($t1, $t4) + 9: $t1 := move($t4) + 10: goto 13 + 11: label L3 + 12: goto 15 + 13: label L4 + 14: goto 2 + 15: label L1 + 16: return $t2 +} + + +[variant baseline] +public fun m::test4($t0: u64): u64 { + var $t1: u64 [unused] + var $t2: u64 + var $t3: bool + var $t4: u64 + var $t5: u64 [unused] + var $t6: u64 [unused] + 0: $t2 := 0 + 1: label L0 + 2: $t4 := 42 + 3: $t3 := <($t2, $t4) + 4: if ($t3) goto 5 else goto 10 + 5: label L2 + 6: $t4 := 1 + 7: $t4 := +($t2, $t4) + 8: $t2 := move($t4) + 9: goto 12 + 10: label L3 + 11: goto 14 + 12: label L4 + 13: goto 1 + 14: label L1 + 15: return $t0 +} + ============ disassembled file-format ================== // Move bytecode v7 @@ -318,7 +461,7 @@ B2: 10: LdU64(1) 11: StLoc[2](loc2: u64) 12: MoveLoc[1](loc1: u64) - 13: CopyLoc[2](loc2: u64) + 13: MoveLoc[2](loc2: u64) 14: Add 15: StLoc[1](loc1: u64) 16: Branch(18) @@ -347,7 +490,7 @@ B2: 8: LdU64(1) 9: StLoc[2](loc1: u64) 10: MoveLoc[1](loc0: u64) - 11: CopyLoc[2](loc1: u64) + 11: MoveLoc[2](loc1: u64) 12: Add 13: StLoc[1](loc0: u64) 14: Branch(16) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_1.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_1.opt.exp index 125b329f68acf..dc7553994cc1a 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_1.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_1.opt.exp @@ -18,6 +18,25 @@ fun m::test($t0: u64): bool { 7: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test($t0: u64): bool { + var $t1: bool + var $t2: u64 + var $t3: u64 + var $t4: u64 + var $t5: u64 + var $t6: u64 + 0: $t2 := copy($t0) + 1: $t3 := copy($t2) + 2: $t4 := move($t3) + 3: $t6 := 1 + 4: $t5 := +($t0, $t6) + 5: $t1 := ==($t2, $t4) + 6: return $t1 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -70,6 +89,24 @@ fun m::test($t0: u64): bool { 6: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test($t0: u64): bool { + var $t1: bool + var $t2: u64 + var $t3: u64 + var $t4: u64 [unused] + var $t5: u64 [unused] + var $t6: u64 + 0: $t2 := copy($t0) + 1: $t3 := copy($t2) + 2: $t6 := 1 + 3: $t0 := +($t0, $t6) + 4: $t1 := ==($t2, $t3) + 5: return $t1 +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_2.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_2.opt.exp index c82ce1c27bc05..3cbb873f10bd0 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_2.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/seq_kills_2.opt.exp @@ -18,6 +18,25 @@ fun m::test($t0: u64): bool { 7: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test($t0: u64): bool { + var $t1: bool + var $t2: u64 + var $t3: u64 + var $t4: u64 + var $t5: u64 + var $t6: u64 + 0: $t2 := copy($t0) + 1: $t3 := move($t2) + 2: $t4 := copy($t3) + 3: $t6 := 1 + 4: $t5 := +($t0, $t6) + 5: $t1 := ==($t3, $t4) + 6: return $t1 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -70,6 +89,24 @@ fun m::test($t0: u64): bool { 6: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::test($t0: u64): bool { + var $t1: bool + var $t2: u64 + var $t3: u64 [unused] + var $t4: u64 + var $t5: u64 [unused] + var $t6: u64 + 0: $t2 := copy($t0) + 1: $t4 := copy($t2) + 2: $t6 := 1 + 3: $t0 := +($t0, $t6) + 4: $t1 := ==($t2, $t4) + 5: return $t1 +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/sequential_assign_struct.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/sequential_assign_struct.opt.exp index c70be3c077a06..ef5799020a8ac 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/sequential_assign_struct.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/sequential_assign_struct.opt.exp @@ -17,6 +17,25 @@ fun m::sequential($t0: m::Foo): m::Foo { 6: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::sequential($t0: m::Foo): m::Foo { + var $t1: m::Foo + var $t2: m::Foo + var $t3: m::Foo + var $t4: m::Foo + var $t5: m::Foo + var $t6: m::Foo + 0: $t2 := move($t0) + 1: $t3 := move($t2) + 2: $t4 := move($t3) + 3: $t5 := move($t4) + 4: $t6 := move($t5) + 5: $t1 := move($t6) + 6: return $t1 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -69,6 +88,19 @@ fun m::sequential($t0: m::Foo): m::Foo { 6: return $t0 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::sequential($t0: m::Foo): m::Foo { + var $t1: m::Foo [unused] + var $t2: m::Foo [unused] + var $t3: m::Foo [unused] + var $t4: m::Foo [unused] + var $t5: m::Foo [unused] + var $t6: m::Foo [unused] + 0: return $t0 +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/simple_sequential_assign.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/simple_sequential_assign.opt.exp index b6b8ce658c6cf..f8f714d03bae3 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/simple_sequential_assign.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/simple_sequential_assign.opt.exp @@ -17,6 +17,25 @@ fun m::sequential($t0: u64): u64 { 6: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::sequential($t0: u64): u64 { + var $t1: u64 + var $t2: u64 + var $t3: u64 + var $t4: u64 + var $t5: u64 + var $t6: u64 + 0: $t2 := move($t0) + 1: $t3 := move($t2) + 2: $t4 := move($t3) + 3: $t5 := move($t4) + 4: $t6 := move($t5) + 5: $t1 := move($t6) + 6: return $t1 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -69,6 +88,19 @@ fun m::sequential($t0: u64): u64 { 6: return $t0 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::sequential($t0: u64): u64 { + var $t1: u64 [unused] + var $t2: u64 [unused] + var $t3: u64 [unused] + var $t4: u64 [unused] + var $t5: u64 [unused] + var $t6: u64 [unused] + 0: return $t0 +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/straight_line_kills.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/straight_line_kills.exp index a4111ed4517b4..244a78cdaba55 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/straight_line_kills.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/straight_line_kills.exp @@ -117,7 +117,7 @@ B0: 7: MoveLoc[3](loc2: u64) 8: Add 9: MoveLoc[2](loc1: u64) - 10: CopyLoc[1](loc0: u64) + 10: MoveLoc[1](loc0: u64) 11: Add 12: StLoc[1](loc0: u64) 13: Pop diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/straight_line_kills.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/straight_line_kills.opt.exp index ee97ea60eb9ab..244a78cdaba55 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/straight_line_kills.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/straight_line_kills.opt.exp @@ -16,6 +16,23 @@ fun m::copy_kill($t0: u64): u64 { 6: return $t1 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::copy_kill($t0: u64): u64 { + var $t1: u64 + var $t2: u64 + var $t3: u64 + var $t4: u64 + var $t5: u64 + 0: $t2 := copy($t0) + 1: $t3 := copy($t2) + 2: $t5 := 1 + 3: $t4 := +($t0, $t5) + 4: $t1 := +($t3, $t2) + 5: return $t1 +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -62,6 +79,23 @@ fun m::copy_kill($t0: u64): u64 { 5: return $t2 } +============ after DeadStoreElimination: ================ + +[variant baseline] +fun m::copy_kill($t0: u64): u64 { + var $t1: u64 [unused] + var $t2: u64 + var $t3: u64 + var $t4: u64 [unused] + var $t5: u64 + 0: $t2 := copy($t0) + 1: $t3 := copy($t2) + 2: $t5 := 1 + 3: $t0 := +($t0, $t5) + 4: $t2 := +($t3, $t2) + 5: return $t2 +} + ============ disassembled file-format ================== // Move bytecode v7 @@ -83,7 +117,7 @@ B0: 7: MoveLoc[3](loc2: u64) 8: Add 9: MoveLoc[2](loc1: u64) - 10: CopyLoc[1](loc0: u64) + 10: MoveLoc[1](loc0: u64) 11: Add 12: StLoc[1](loc0: u64) 13: Pop diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/swap.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/swap.opt.exp index 7a47ac8cec46d..64990776e2cdc 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/swap.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/swap.opt.exp @@ -13,6 +13,21 @@ public fun m::test($t0: u64, $t1: u64): (u64, u64) { 5: return ($t2, $t3) } +============ after DeadStoreElimination: ================ + +[variant baseline] +public fun m::test($t0: u64, $t1: u64): (u64, u64) { + var $t2: u64 + var $t3: u64 + var $t4: u64 + 0: $t4 := move($t0) + 1: $t0 := move($t1) + 2: $t1 := move($t4) + 3: $t2 := move($t0) + 4: $t3 := move($t1) + 5: return ($t2, $t3) +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -54,6 +69,19 @@ public fun m::test($t0: u64, $t1: u64): (u64, u64) { 5: return ($t0, $t1) } +============ after DeadStoreElimination: ================ + +[variant baseline] +public fun m::test($t0: u64, $t1: u64): (u64, u64) { + var $t2: u64 [unused] + var $t3: u64 [unused] + var $t4: u64 + 0: $t4 := move($t0) + 1: $t0 := move($t1) + 2: $t1 := move($t4) + 3: return ($t0, $t1) +} + ============ disassembled file-format ================== // Move bytecode v7 diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/swap_in_a_loop.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/swap_in_a_loop.exp index e20f4d73682af..db6c1acb9f291 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/swap_in_a_loop.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/swap_in_a_loop.exp @@ -234,7 +234,7 @@ B2: 14: LdU64(1) 15: StLoc[3](loc1: u64) 16: MoveLoc[2](loc0: u64) - 17: CopyLoc[3](loc1: u64) + 17: MoveLoc[3](loc1: u64) 18: Sub 19: StLoc[2](loc0: u64) 20: Branch(22) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/swap_in_a_loop.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/swap_in_a_loop.opt.exp index 43cd145f552eb..db6c1acb9f291 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/swap_in_a_loop.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/swap_in_a_loop.opt.exp @@ -33,6 +33,41 @@ public fun m::test($t0: u64, $t1: u64): (u64, u64) { 20: return ($t2, $t3) } +============ after DeadStoreElimination: ================ + +[variant baseline] +public fun m::test($t0: u64, $t1: u64): (u64, u64) { + var $t2: u64 + var $t3: u64 + var $t4: u64 + var $t5: u64 + var $t6: bool + var $t7: u64 + var $t8: u64 + var $t9: u64 + 0: $t4 := copy($t0) + 1: label L0 + 2: $t7 := 0 + 3: $t6 := >($t4, $t7) + 4: if ($t6) goto 5 else goto 13 + 5: label L2 + 6: $t5 := move($t0) + 7: $t0 := move($t1) + 8: $t1 := move($t5) + 9: $t9 := 1 + 10: $t8 := -($t4, $t9) + 11: $t4 := move($t8) + 12: goto 15 + 13: label L3 + 14: goto 17 + 15: label L4 + 16: goto 1 + 17: label L1 + 18: $t2 := move($t0) + 19: $t3 := move($t1) + 20: return ($t2, $t3) +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -137,6 +172,39 @@ public fun m::test($t0: u64, $t1: u64): (u64, u64) { 20: return ($t0, $t1) } +============ after DeadStoreElimination: ================ + +[variant baseline] +public fun m::test($t0: u64, $t1: u64): (u64, u64) { + var $t2: u64 [unused] + var $t3: u64 [unused] + var $t4: u64 + var $t5: u64 [unused] + var $t6: bool + var $t7: u64 + var $t8: u64 [unused] + var $t9: u64 [unused] + 0: $t4 := copy($t0) + 1: label L0 + 2: $t7 := 0 + 3: $t6 := >($t4, $t7) + 4: if ($t6) goto 5 else goto 13 + 5: label L2 + 6: $t7 := move($t0) + 7: $t0 := move($t1) + 8: $t1 := move($t7) + 9: $t7 := 1 + 10: $t7 := -($t4, $t7) + 11: $t4 := move($t7) + 12: goto 15 + 13: label L3 + 14: goto 17 + 15: label L4 + 16: goto 1 + 17: label L1 + 18: return ($t0, $t1) +} + ============ disassembled file-format ================== // Move bytecode v7 @@ -166,7 +234,7 @@ B2: 14: LdU64(1) 15: StLoc[3](loc1: u64) 16: MoveLoc[2](loc0: u64) - 17: CopyLoc[3](loc1: u64) + 17: MoveLoc[3](loc1: u64) 18: Sub 19: StLoc[2](loc0: u64) 20: Branch(22) diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/unused_add.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/unused_add.opt.exp index 1dcdd78ccbb1c..e68cdb2000a38 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/unused_add.opt.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/unused_add.opt.exp @@ -13,6 +13,13 @@ public fun m::test() { 0: return () } +============ after DeadStoreElimination: ================ + +[variant baseline] +public fun m::test() { + 0: return () +} + ============ after VariableCoalescingAnnotator: ================ [variant baseline] @@ -28,6 +35,13 @@ public fun m::test() { 0: return () } +============ after DeadStoreElimination: ================ + +[variant baseline] +public fun m::test() { + 0: return () +} + ============ disassembled file-format ================== // Move bytecode v7 From 85d754622b8fe8c2d7e26b5ae63e77b9fc65f338 Mon Sep 17 00:00:00 2001 From: Brian Olson Date: Fri, 5 Apr 2024 12:04:41 -0400 Subject: [PATCH 10/36] github action summary for rust unit tests (#12767) * github action summary for rust unit tests * also print failing test names to stdout so that it's handy at the end of the log * if no failures, maybe show flakey tests --- .github/actions/rust-unit-tests/action.yaml | 3 +- .../rust-unit-tests/nextest_summary.py | 90 +++++++++++++++++++ 2 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 .github/actions/rust-unit-tests/nextest_summary.py diff --git a/.github/actions/rust-unit-tests/action.yaml b/.github/actions/rust-unit-tests/action.yaml index a1d5beb99b4cb..f68562c6fbeb5 100644 --- a/.github/actions/rust-unit-tests/action.yaml +++ b/.github/actions/rust-unit-tests/action.yaml @@ -45,8 +45,9 @@ runs: # Run the rust unit tests - name: Run all unit tests run: | - NEXTEST_EXPERIMENTAL_LIBTEST_JSON=1 cargo nextest run --profile ci --cargo-profile ci --locked --workspace --exclude smoke-test --exclude aptos-testcases --retries 3 --no-fail-fast --message-format libtest-json > nextest_output.json + NEXTEST_EXPERIMENTAL_LIBTEST_JSON=1 cargo nextest run --profile ci --cargo-profile ci --locked --workspace --exclude smoke-test --exclude aptos-testcases --retries 3 --no-fail-fast --message-format libtest-json > nextest_output.json || python3 .github/actions/rust-unit-tests/nextest_summary.py nextest_output.json "$GITHUB_STEP_SUMMARY" -f buildkite-test-collector < nextest_output.json || echo "Warning: buildkite-test-collector encountered an error" + python3 .github/actions/rust-unit-tests/nextest_summary.py nextest_output.json "$GITHUB_STEP_SUMMARY" || echo "summary generation had an error" rm nextest_output.json shell: bash env: diff --git a/.github/actions/rust-unit-tests/nextest_summary.py b/.github/actions/rust-unit-tests/nextest_summary.py new file mode 100644 index 0000000000000..3a9398ed632d8 --- /dev/null +++ b/.github/actions/rust-unit-tests/nextest_summary.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python + +import argparse +import json +import sys + +# how many failed tests to name before it's too many ... +FAIL_HEAD_LINES = 20 + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument('nextest_json') + ap.add_argument('summary_out_path') + ap.add_argument('-f', '--fail', default=False, action='store_true') + args = ap.parse_args() + + badlines = 0 + eventCounts = {} + failnames = [] + flakey = [] + with open(args.nextest_json, 'rt') as fin: + for line in fin: + try: + rec = json.loads(line) + except Exception as e: + badlines += 1 + if badlines < 10: + print(e) + continue + rectype = rec.get('type') + if rectype != 'test': + continue + event = rec.get('event') + if event == 'started': + continue + eventCounts[event] = eventCounts.get(event, 0) + 1 + if event == 'failed': + failnames.append(rec.get('name', '_')) + if event == 'ok': + testname = rec.get('name', '_') + if '#' in testname: + # flakey test passed on retry + flakey.append(rec) + with open(args.summary_out_path, 'at') as fout: + rows = [] + for event in ('ok', 'ignored', 'failed'): + ec = eventCounts.pop(event, 0) + style = "" + if event == 'failed': + style = ' style="font-weight:bold;font-size:120%;color:#f00;"' + rows.append(f'{ec}{event}') + for event, ec in eventCounts.items(): + rows.append(f'{ec}{event}') + if badlines != 0: + rows.append(f'{badlines}bad lines') + fout.write('' + ''.join(rows) + '
\n\n') + if failnames: + failnames.sort() + failshow = failnames + if len(failnames) > FAIL_HEAD_LINES: + failshow = failnames[:FAIL_HEAD_LINES] + fout.write('## Failed\n\n') + for fn in failshow: + fout.write(f' {fn}\n') + if len(failnames) > FAIL_HEAD_LINES: + fout.write(f' ... and {len(failnames)-FAIL_HEAD_LINES} more\n') + fout.write('\n') + elif flakey: + flakeshow = flakey + if len(flakeshow) > FAIL_HEAD_LINES: + flakeshow = flakeshow[:FAIL_HEAD_LINES] + fout.write("## Flakey\n\n") + for rec in flakeshow: + name = rec['name'] + etime = rec.get('exec_time', '') + fout.write(f" {name} ({etime})\n") + if len(flakey) > FAIL_HEAD_LINES: + fout.write(f" ... and {len(flakey)-FAIL_HEAD_LINES} more\n") + fout.write("\n") + if failnames: + print(f"{len(failnames)} FAILING tests:") + print("\n".join(failnames)) + print(f"{len(failnames)} FAILING tests") + if eventCounts.get('failed',0) != 0: + sys.exit(1) + if args.fail: + sys.exit(1) + +if __name__ == '__main__': + main() From f331c78d7d21e0e3fe04a4eecca903074725c867 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Apr 2024 17:57:05 +0000 Subject: [PATCH 11/36] Bump h2 from 0.3.22 to 0.3.24 (#11703) Bumps [h2](https://github.com/hyperium/h2) from 0.3.22 to 0.3.24. - [Release notes](https://github.com/hyperium/h2/releases) - [Changelog](https://github.com/hyperium/h2/blob/v0.3.24/CHANGELOG.md) - [Commits](https://github.com/hyperium/h2/compare/v0.3.22...v0.3.24) --- updated-dependencies: - dependency-name: h2 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index ddc50b4f8bdc7..bd85b5e59dfde 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8777,7 +8777,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.5.5", + "socket2 0.4.10", "tokio", "tower-service", "tracing", From 4a10bed8d47677d818d00fd095d31bea45a9b290 Mon Sep 17 00:00:00 2001 From: John C Date: Fri, 5 Apr 2024 11:35:45 -0700 Subject: [PATCH 12/36] Add collection address, old and new values to collection mutation events (#12807) --- .../aptos-token-objects/doc/collection.md | 41 ++++++++++++++++--- .../sources/collection.move | 30 ++++++++++---- 2 files changed, 59 insertions(+), 12 deletions(-) diff --git a/aptos-move/framework/aptos-token-objects/doc/collection.md b/aptos-move/framework/aptos-token-objects/doc/collection.md index 9f18ac38f532a..bbe8f7ec3daab 100644 --- a/aptos-move/framework/aptos-token-objects/doc/collection.md +++ b/aptos-move/framework/aptos-token-objects/doc/collection.md @@ -211,6 +211,24 @@ directly understand the behavior in a writeset.
+
+
+collection: object::Object<collection::Collection> +
+
+ +
+
+old_value: string::String +
+
+ +
+
+new_value: string::String +
+
+
@@ -612,7 +630,13 @@ If max_value is not set to U64_MAX, this ensures that a limited number of tokens
-max_supply: u64 +old_max_supply: u64 +
+
+ +
+
+new_max_supply: u64
@@ -1598,10 +1622,14 @@ Once the collection has been created, the collection address should be saved for
public fun set_name(mutator_ref: &MutatorRef, name: String) acquires Collection {
     assert!(string::length(&name) <= MAX_COLLECTION_NAME_LENGTH, error::out_of_range(ECOLLECTION_NAME_TOO_LONG));
     let collection = borrow_mut(mutator_ref);
+    let old_name = collection.name;
     collection.name = name;
-    event::emit(
-        Mutation { mutated_field_name: string::utf8(b"name") },
-    );
+    event::emit(Mutation {
+        mutated_field_name: string::utf8(b"name") ,
+        collection: object::address_to_object(mutator_ref.self),
+        old_value: old_name,
+        new_value: name,
+    });
 }
 
@@ -1687,6 +1715,7 @@ Once the collection has been created, the collection address should be saved for
public fun set_max_supply(mutator_ref: &MutatorRef, max_supply: u64) acquires ConcurrentSupply, FixedSupply {
     let collection = object::address_to_object<Collection>(mutator_ref.self);
     let collection_address = object::object_address(&collection);
+    let old_max_supply;
 
     if (exists<ConcurrentSupply>(collection_address)) {
         let supply = borrow_global_mut<ConcurrentSupply>(collection_address);
@@ -1695,6 +1724,7 @@ Once the collection has been created, the collection address should be saved for
             max_supply >= current_supply,
             error::out_of_range(EINVALID_MAX_SUPPLY),
         );
+        old_max_supply = aggregator_v2::max_value(&supply.current_supply);
         supply.current_supply = aggregator_v2::create_aggregator(max_supply);
         aggregator_v2::add(&mut supply.current_supply, current_supply);
     } else if (exists<FixedSupply>(collection_address)) {
@@ -1703,12 +1733,13 @@ Once the collection has been created, the collection address should be saved for
             max_supply >= supply.current_supply,
             error::out_of_range(EINVALID_MAX_SUPPLY),
         );
+        old_max_supply = supply.max_supply;
         supply.max_supply = max_supply;
     } else {
         abort error::invalid_argument(ENO_MAX_SUPPLY_IN_COLLECTION)
     };
 
-    event::emit(SetMaxSupply { collection, max_supply });
+    event::emit(SetMaxSupply { collection, old_max_supply, new_max_supply: max_supply });
 }
 
diff --git a/aptos-move/framework/aptos-token-objects/sources/collection.move b/aptos-move/framework/aptos-token-objects/sources/collection.move index 9f6e4940c56c0..74ad95d9e3623 100644 --- a/aptos-move/framework/aptos-token-objects/sources/collection.move +++ b/aptos-move/framework/aptos-token-objects/sources/collection.move @@ -89,6 +89,9 @@ module aptos_token_objects::collection { /// directly understand the behavior in a writeset. struct Mutation has drop, store { mutated_field_name: String, + collection: Object, + old_value: String, + new_value: String, } #[resource_group_member(group = aptos_framework::object::ObjectGroup)] @@ -171,7 +174,8 @@ module aptos_token_objects::collection { #[event] struct SetMaxSupply has drop, store { collection: Object, - max_supply: u64, + old_max_supply: u64, + new_max_supply: u64, } /// Creates a fixed-sized collection, or a collection that supports a fixed amount of tokens. @@ -618,10 +622,14 @@ module aptos_token_objects::collection { public fun set_name(mutator_ref: &MutatorRef, name: String) acquires Collection { assert!(string::length(&name) <= MAX_COLLECTION_NAME_LENGTH, error::out_of_range(ECOLLECTION_NAME_TOO_LONG)); let collection = borrow_mut(mutator_ref); + let old_name = collection.name; collection.name = name; - event::emit( - Mutation { mutated_field_name: string::utf8(b"name") }, - ); + event::emit(Mutation { + mutated_field_name: string::utf8(b"name") , + collection: object::address_to_object(mutator_ref.self), + old_value: old_name, + new_value: name, + }); } public fun set_description(mutator_ref: &MutatorRef, description: String) acquires Collection { @@ -647,6 +655,7 @@ module aptos_token_objects::collection { public fun set_max_supply(mutator_ref: &MutatorRef, max_supply: u64) acquires ConcurrentSupply, FixedSupply { let collection = object::address_to_object(mutator_ref.self); let collection_address = object::object_address(&collection); + let old_max_supply; if (exists(collection_address)) { let supply = borrow_global_mut(collection_address); @@ -655,6 +664,7 @@ module aptos_token_objects::collection { max_supply >= current_supply, error::out_of_range(EINVALID_MAX_SUPPLY), ); + old_max_supply = aggregator_v2::max_value(&supply.current_supply); supply.current_supply = aggregator_v2::create_aggregator(max_supply); aggregator_v2::add(&mut supply.current_supply, current_supply); } else if (exists(collection_address)) { @@ -663,12 +673,13 @@ module aptos_token_objects::collection { max_supply >= supply.current_supply, error::out_of_range(EINVALID_MAX_SUPPLY), ); + old_max_supply = supply.max_supply; supply.max_supply = max_supply; } else { abort error::invalid_argument(ENO_MAX_SUPPLY_IN_COLLECTION) }; - event::emit(SetMaxSupply { collection, max_supply }); + event::emit(SetMaxSupply { collection, old_max_supply, new_max_supply: max_supply }); } // Tests @@ -776,6 +787,9 @@ module aptos_token_objects::collection { assert!(new_collection_name == name(collection), 1); event::was_event_emitted(&Mutation { mutated_field_name: string::utf8(b"name"), + collection, + old_value: collection_name, + new_value: new_collection_name, }); } @@ -826,7 +840,8 @@ module aptos_token_objects::collection { event::was_event_emitted(&SetMaxSupply { collection: object::address_to_object(collection_address), - max_supply: new_max_supply, + old_max_supply: max_supply, + new_max_supply, }); } @@ -860,7 +875,8 @@ module aptos_token_objects::collection { event::was_event_emitted(&SetMaxSupply { collection: object::address_to_object(collection_address), - max_supply: current_supply, + old_max_supply: current_supply, + new_max_supply: current_supply, }); } From a6dcf1594596dc6493f4a3e116d19d505610e699 Mon Sep 17 00:00:00 2001 From: Alan Luong Date: Fri, 5 Apr 2024 15:29:58 -0400 Subject: [PATCH 13/36] always send json formatted logs to the telemetry service (#12639) --- crates/aptos-logger/src/aptos_logger.rs | 92 +++++++++++++++++++++++-- 1 file changed, 86 insertions(+), 6 deletions(-) diff --git a/crates/aptos-logger/src/aptos_logger.rs b/crates/aptos-logger/src/aptos_logger.rs index c327fd82579b6..fccad69b2af44 100644 --- a/crates/aptos-logger/src/aptos_logger.rs +++ b/crates/aptos-logger/src/aptos_logger.rs @@ -23,8 +23,8 @@ use once_cell::sync::Lazy; use serde::{ser::SerializeStruct, Serialize, Serializer}; use std::{ collections::BTreeMap, - env, fmt, - fmt::Debug, + env, + fmt::{self, Debug}, io::{Stdout, Write}, ops::{Deref, DerefMut}, str::FromStr, @@ -626,7 +626,7 @@ impl LoggerService { .telemetry_filter .enabled(&entry.metadata) { - let s = (self.facade.formatter)(&entry).expect("Unable to format"); + let s = json_format(&entry).expect("Unable to format"); let _ = writer.write(s); } } @@ -802,15 +802,17 @@ impl LoggerFilterUpdater { #[cfg(test)] mod tests { - use super::{AptosData, LogEntry}; + use super::{text_format, AptosData, LogEntry}; use crate::{ aptos_logger::{json_format, TruncatedLogString, RUST_LOG_TELEMETRY}, debug, error, info, logger::Logger, + telemetry_log_writer::TelemetryLog, trace, warn, AptosDataBuilder, Event, Key, KeyValue, Level, LoggerFilterUpdater, Metadata, - Schema, Value, Visitor, + Schema, Value, Visitor, Writer, }; use chrono::{DateTime, Utc}; + use futures::StreamExt; #[cfg(test)] use pretty_assertions::assert_eq; use serde_json::Value as JsonValue; @@ -818,10 +820,34 @@ mod tests { env, sync::{ mpsc::{self, Receiver, SyncSender}, - Arc, + Arc, Mutex, }, thread, + time::Duration, }; + use tokio::time; + + pub struct MockWriter { + pub logs: Arc>>, + } + + impl Writer for MockWriter { + fn write(&self, log: String) { + let mut logs = self.logs.lock().unwrap(); + logs.push(log); + } + + fn write_buferred(&mut self, log: String) { + self.write(log); + } + } + + impl MockWriter { + pub fn new() -> (Self, Arc>>) { + let logs = Arc::new(Mutex::new(Vec::new())); + (Self { logs: logs.clone() }, logs) + } + } #[derive(serde::Serialize)] #[serde(rename_all = "snake_case")] @@ -1035,6 +1061,60 @@ mod tests { (logger_builder, logger) } + fn new_text_logger() -> ( + Arc, + Arc>>, + futures::channel::mpsc::Receiver, + ) { + let (tx, rx) = futures::channel::mpsc::channel(100); + let (mock_writer, logs) = MockWriter::new(); + + let logger = AptosDataBuilder::new() + .level(Level::Debug) + .telemetry_level(Level::Debug) + .remote_log_tx(tx) + .custom_format(text_format) + .printer(Box::new(mock_writer)) + .is_async(true) + .build_logger(); + + (logger, logs, rx) + } + + #[tokio::test] + async fn telemetry_logs_always_json_formatted() { + let (logger, local_logs, mut rx) = new_text_logger(); + + let metadata = Metadata::new( + Level::Info, + env!("CARGO_CRATE_NAME"), + module_path!(), + concat!(file!(), ':', line!()), + ); + + let event = &Event::new(&metadata, Some(format_args!("This is a log message")), &[]); + logger.record(event); + logger.flush(); + + { + let local_logs = local_logs.lock().unwrap(); + assert!(serde_json::from_str::(&local_logs[0]).is_err()); + } + + let timeout_duration = Duration::from_secs(5); + if let Ok(Some(TelemetryLog::Log(telemetry_log))) = + time::timeout(timeout_duration, rx.next()).await + { + assert!( + serde_json::from_str::(&telemetry_log).is_ok(), + "Telemetry logs not in JSON format: {}", + telemetry_log + ); + } else { + panic!("Timed out waiting for telemetry log"); + } + } + #[test] fn test_logger_filter_updater() { let (logger_builder, logger) = new_async_logger(); From a1a62174e9c3ae308bbaee3b37e665a3068b2235 Mon Sep 17 00:00:00 2001 From: Balaji Arun Date: Fri, 5 Apr 2024 13:40:22 -0700 Subject: [PATCH 14/36] [api] specify method for all endpoints (#12771) --- api/src/log.rs | 2 +- api/src/runtime.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/src/log.rs b/api/src/log.rs index f305815176d00..b7324dc8862ba 100644 --- a/api/src/log.rs +++ b/api/src/log.rs @@ -77,7 +77,7 @@ pub async fn middleware_log(next: E, request: Request) -> Result() .map(|operation_id| operation_id.0) - .unwrap_or("operation_id_not_set"); + .unwrap_or(&log.path); // Log response status per-endpoint + method. HISTOGRAM diff --git a/api/src/runtime.rs b/api/src/runtime.rs index aacab86b4024b..4673c087235a1 100644 --- a/api/src/runtime.rs +++ b/api/src/runtime.rs @@ -217,13 +217,13 @@ pub fn attach_poem_to_runtime( // Build routes for the API let route = Route::new() - .at("/", root_handler) + .at("/", poem::get(root_handler)) .nest( "/v1", Route::new() .nest("/", api_service) - .at("/spec.json", spec_json) - .at("/spec.yaml", spec_yaml) + .at("/spec.json", poem::get(spec_json)) + .at("/spec.yaml", poem::get(spec_yaml)) // TODO: We add this manually outside of the OpenAPI spec for now. // https://github.com/poem-web/poem/issues/364 .at( From dec20a6982e20018656f56d9bbfc34b52f9ed22a Mon Sep 17 00:00:00 2001 From: igor-aptos <110557261+igor-aptos@users.noreply.github.com> Date: Fri, 5 Apr 2024 14:50:18 -0700 Subject: [PATCH 15/36] [forge][success_criteria] Fix forge check for error!() logs (#12801) * Fix forge check for error logs * downgrade randomness missing error!() for first two epochs * downgrading dkg wrong epoch --------- --- aptos-move/e2e-benchmark/src/main.rs | 6 +++++- consensus/src/epoch_manager.rs | 15 +++++++++++---- dkg/src/dkg_manager/mod.rs | 13 ++++++++----- .../forge/src/interface/prometheus_metrics.rs | 2 +- testsuite/forge/src/success_criteria.rs | 6 +++++- 5 files changed, 30 insertions(+), 12 deletions(-) diff --git a/aptos-move/e2e-benchmark/src/main.rs b/aptos-move/e2e-benchmark/src/main.rs index 3ef5cc4d3933f..b9a66d46ef3b5 100644 --- a/aptos-move/e2e-benchmark/src/main.rs +++ b/aptos-move/e2e-benchmark/src/main.rs @@ -230,5 +230,9 @@ fn main() { } // Assert there were no error log lines in the run. - assert_eq!(0, aptos_logger::ERROR_LOG_COUNT.get()); + assert_eq!( + 0, + aptos_logger::ERROR_LOG_COUNT.get(), + "Error logs were found in the run." + ); } diff --git a/consensus/src/epoch_manager.rs b/consensus/src/epoch_manager.rs index 48a78236a1ac6..77e8e944f1489 100644 --- a/consensus/src/epoch_manager.rs +++ b/consensus/src/epoch_manager.rs @@ -1086,10 +1086,17 @@ impl EpochManager

{ Ok((rand_config, fast_rand_config)) => (Some(rand_config), fast_rand_config), Err(reason) => { if onchain_randomness_config.randomness_enabled() { - error!( - "Failed to get randomness config for new epoch: {:?}", - reason - ); + if epoch_state.epoch > 2 { + error!( + "Failed to get randomness config for new epoch [{}]: {:?}", + epoch_state.epoch, reason + ); + } else { + warn!( + "Failed to get randomness config for new epoch [{}]: {:?}", + epoch_state.epoch, reason + ); + } } (None, None) }, diff --git a/dkg/src/dkg_manager/mod.rs b/dkg/src/dkg_manager/mod.rs index 7104027ebd765..d12b5aa7b12ba 100644 --- a/dkg/src/dkg_manager/mod.rs +++ b/dkg/src/dkg_manager/mod.rs @@ -9,7 +9,7 @@ use anyhow::{anyhow, bail, ensure, Result}; use aptos_channels::{aptos_channel, message_queues::QueueStyle}; use aptos_crypto::Uniform; use aptos_infallible::duration_since_epoch; -use aptos_logger::{debug, error, info}; +use aptos_logger::{debug, error, info, warn}; use aptos_types::{ dkg::{ DKGSessionMetadata, DKGSessionState, DKGStartEvent, DKGTrait, DKGTranscript, @@ -423,10 +423,13 @@ impl DKGManager { matches!(&self.state, InnerState::NotStarted), "[DKG] dkg already started" ); - ensure!( - self.epoch_state.epoch == session_metadata.dealer_epoch, - "[DKG] event not for current epoch" - ); + if self.epoch_state.epoch != session_metadata.dealer_epoch { + warn!( + "[DKG] event (from epoch {}) not for current epoch ({}), ignoring", + session_metadata.dealer_epoch, self.epoch_state.epoch + ); + return Ok(()); + } self.setup_deal_broadcast(start_time_us, &session_metadata) .await } diff --git a/testsuite/forge/src/interface/prometheus_metrics.rs b/testsuite/forge/src/interface/prometheus_metrics.rs index e8dd17dc90d40..6edcdbe4f81f1 100644 --- a/testsuite/forge/src/interface/prometheus_metrics.rs +++ b/testsuite/forge/src/interface/prometheus_metrics.rs @@ -59,7 +59,7 @@ impl SystemMetrics { } pub async fn fetch_error_metrics(swarm: &dyn Swarm) -> anyhow::Result { - let error_query = r#"aptos_error_log_count{container=~"validator"}"#; + let error_query = r#"aptos_error_log_count{role=~"validator"}"#; let result = swarm.query_metrics(error_query, None, None).await?; let error_samples = result.as_instant().unwrap_or(&[]); diff --git a/testsuite/forge/src/success_criteria.rs b/testsuite/forge/src/success_criteria.rs index fea6aeefefba5..7071843123b1f 100644 --- a/testsuite/forge/src/success_criteria.rs +++ b/testsuite/forge/src/success_criteria.rs @@ -549,8 +549,12 @@ impl SuccessCriteriaChecker { async fn check_no_errors(swarm: &mut dyn Swarm) -> anyhow::Result<()> { let error_count = fetch_error_metrics(swarm).await?; if error_count > 0 { - bail!("Error count was {} and should be 0", error_count); + bail!( + "error!() count in validator logs was {}, and must be 0", + error_count + ); } else { + println!("No error!() found in validator logs"); Ok(()) } } From 6b0bad099978d1d7ca9d38c1f753ad46b76dbba4 Mon Sep 17 00:00:00 2001 From: igor-aptos <110557261+igor-aptos@users.noreply.github.com> Date: Fri, 5 Apr 2024 15:40:21 -0700 Subject: [PATCH 16/36] Add liquidity pool swap (from examples) to transaction generator (#12805) --- aptos-move/e2e-benchmark/src/main.rs | 13 +- aptos-move/e2e-tests/src/executor.rs | 2 +- crates/transaction-generator-lib/src/args.rs | 12 + .../src/publishing/module_simple.rs | 36 +- .../src/publishing/raw_module_data.rs | 581 ++++++++++++++++- .../src/packages/complex/Move.toml | 2 + .../sources/liquid_pool/liquidity_pool.move | 612 ++++++++++++++++++ .../liquid_pool/liquidity_pool_wrapper.move | 120 ++++ testsuite/single_node_performance.py | 6 + 9 files changed, 1363 insertions(+), 21 deletions(-) create mode 100644 testsuite/module-publish/src/packages/complex/sources/liquid_pool/liquidity_pool.move create mode 100644 testsuite/module-publish/src/packages/complex/sources/liquid_pool/liquidity_pool_wrapper.move diff --git a/aptos-move/e2e-benchmark/src/main.rs b/aptos-move/e2e-benchmark/src/main.rs index b9a66d46ef3b5..dd05848e3f02d 100644 --- a/aptos-move/e2e-benchmark/src/main.rs +++ b/aptos-move/e2e-benchmark/src/main.rs @@ -33,7 +33,11 @@ pub fn execute_txn( let txn_output = executor.execute_transaction(sign_tx); executor.apply_write_set(txn_output.write_set()); - assert!(txn_output.status().status().unwrap().is_success()); + assert!( + txn_output.status().status().unwrap().is_success(), + "txn failed with {:?}", + txn_output.status() + ); } fn execute_and_time_entry_point( @@ -138,6 +142,8 @@ fn main() { (257, EntryPoints::TokenV1MintAndTransferFT), (412, EntryPoints::TokenV1MintAndTransferNFTSequential), (368, EntryPoints::TokenV2AmbassadorMint { numbered: true }), + (520, EntryPoints::LiquidityPoolSwap { is_stable: true }), + (500, EntryPoints::LiquidityPoolSwap { is_stable: false }), ]; let mut failures = Vec::new(); @@ -160,6 +166,7 @@ fn main() { 0, package.publish_transaction_payload(), ); + println!("Published package: {:?}", entry_point.package_name()); if let Some(init_entry_point) = entry_point.initialize_entry_point() { execute_txn( &mut executor, @@ -171,6 +178,10 @@ fn main() { Some(publisher.address()), ), ); + println!( + "Executed init entry point: {:?}", + entry_point.initialize_entry_point() + ); } let elapsed_micros = execute_and_time_entry_point( diff --git a/aptos-move/e2e-tests/src/executor.rs b/aptos-move/e2e-tests/src/executor.rs index 5519df46ed6dd..054d28320a2a5 100644 --- a/aptos-move/e2e-tests/src/executor.rs +++ b/aptos-move/e2e-tests/src/executor.rs @@ -924,7 +924,7 @@ impl FakeExecutor { let elapsed = start.elapsed(); if let Err(err) = result { if !should_error { - println!("Should error, but ignoring for now... {}", err); + println!("Shouldn't error, but ignoring for now... {}", err); } } times.push(elapsed.as_micros()); diff --git a/crates/transaction-generator-lib/src/args.rs b/crates/transaction-generator-lib/src/args.rs index 496735226c5f3..af84253171f7a 100644 --- a/crates/transaction-generator-lib/src/args.rs +++ b/crates/transaction-generator-lib/src/args.rs @@ -57,6 +57,8 @@ pub enum TransactionTypeArg { FungibleAssetMint, TokenV2AmbassadorMint, TokenV2AmbassadorMintAndBurn1M, + LiquidityPoolSwap, + LiquidityPoolSwapStable, VectorPictureCreate30k, VectorPicture30k, VectorPictureRead30k, @@ -351,6 +353,16 @@ impl TransactionTypeArg { use_account_pool: sender_use_account_pool, progress_type: workflow_progress_type, }, + TransactionTypeArg::LiquidityPoolSwap => TransactionType::CallCustomModules { + entry_point: EntryPoints::LiquidityPoolSwap { is_stable: false }, + num_modules: module_working_set_size, + use_account_pool: sender_use_account_pool, + }, + TransactionTypeArg::LiquidityPoolSwapStable => TransactionType::CallCustomModules { + entry_point: EntryPoints::LiquidityPoolSwap { is_stable: true }, + num_modules: module_working_set_size, + use_account_pool: sender_use_account_pool, + }, TransactionTypeArg::VectorPictureCreate30k => TransactionType::CallCustomModules { entry_point: EntryPoints::InitializeVectorPicture { length: 30 * 1024 }, num_modules: module_working_set_size, diff --git a/crates/transaction-generator-lib/src/publishing/module_simple.rs b/crates/transaction-generator-lib/src/publishing/module_simple.rs index 7b43465b3dc47..3ce59c4b8533e 100644 --- a/crates/transaction-generator-lib/src/publishing/module_simple.rs +++ b/crates/transaction-generator-lib/src/publishing/module_simple.rs @@ -231,6 +231,13 @@ pub enum EntryPoints { /// Burn an NFT token, only works with numbered=false tokens. TokenV2AmbassadorBurn, + LiquidityPoolSwapInit { + is_stable: bool, + }, + LiquidityPoolSwap { + is_stable: bool, + }, + InitializeVectorPicture { length: u64, }, @@ -291,7 +298,9 @@ impl EntryPoints { EntryPoints::TokenV2AmbassadorMint { .. } | EntryPoints::TokenV2AmbassadorBurn => { "ambassador_token" }, - EntryPoints::InitializeVectorPicture { .. } + EntryPoints::LiquidityPoolSwapInit { .. } + | EntryPoints::LiquidityPoolSwap { .. } + | EntryPoints::InitializeVectorPicture { .. } | EntryPoints::VectorPicture { .. } | EntryPoints::VectorPictureRead { .. } | EntryPoints::InitializeSmartTablePicture @@ -343,6 +352,9 @@ impl EntryPoints { EntryPoints::TokenV2AmbassadorMint { .. } | EntryPoints::TokenV2AmbassadorBurn => { "ambassador" }, + EntryPoints::LiquidityPoolSwapInit { .. } | EntryPoints::LiquidityPoolSwap { .. } => { + "liquidity_pool_wrapper" + }, EntryPoints::InitializeVectorPicture { .. } | EntryPoints::VectorPicture { .. } | EntryPoints::VectorPictureRead { .. } => "vector_picture", @@ -593,6 +605,20 @@ impl EntryPoints { ident_str!("burn_named_by_user").to_owned(), vec![], ), + + EntryPoints::LiquidityPoolSwapInit { is_stable } => get_payload( + module_id, + ident_str!("initialize_liquid_pair").to_owned(), + vec![bcs::to_bytes(&is_stable).unwrap()], + ), + EntryPoints::LiquidityPoolSwap { is_stable } => { + let rng: &mut StdRng = rng.expect("Must provide RNG"); + let from_1: bool = (rng.gen_range(0, 2) == 1); + get_payload(module_id, ident_str!("swap").to_owned(), vec![ + bcs::to_bytes(&rng.gen_range(1000u64, 2000u64)).unwrap(), // amount_in + bcs::to_bytes(&from_1).unwrap(), // from_1 + ]) + }, EntryPoints::InitializeVectorPicture { length } => { get_payload(module_id, ident_str!("create").to_owned(), vec![ bcs::to_bytes(&length).unwrap(), // length @@ -653,6 +679,11 @@ impl EntryPoints { | EntryPoints::TokenV1MintAndTransferFT => { Some(EntryPoints::TokenV1InitializeCollection) }, + EntryPoints::LiquidityPoolSwap { is_stable } => { + Some(EntryPoints::LiquidityPoolSwapInit { + is_stable: *is_stable, + }) + }, EntryPoints::VectorPicture { length } | EntryPoints::VectorPictureRead { length } => { Some(EntryPoints::InitializeVectorPicture { length: *length }) }, @@ -674,6 +705,7 @@ impl EntryPoints { EntryPoints::TokenV2AmbassadorMint { .. } | EntryPoints::TokenV2AmbassadorBurn => { MultiSigConfig::Publisher }, + EntryPoints::LiquidityPoolSwap { .. } => MultiSigConfig::Publisher, _ => MultiSigConfig::None, } } @@ -724,6 +756,8 @@ impl EntryPoints { EntryPoints::TokenV2AmbassadorMint { .. } | EntryPoints::TokenV2AmbassadorBurn => { AutomaticArgs::SignerAndMultiSig }, + EntryPoints::LiquidityPoolSwapInit { .. } => AutomaticArgs::Signer, + EntryPoints::LiquidityPoolSwap { .. } => AutomaticArgs::SignerAndMultiSig, EntryPoints::InitializeVectorPicture { .. } => AutomaticArgs::Signer, EntryPoints::VectorPicture { .. } | EntryPoints::VectorPictureRead { .. } => { AutomaticArgs::None diff --git a/crates/transaction-generator-lib/src/publishing/raw_module_data.rs b/crates/transaction-generator-lib/src/publishing/raw_module_data.rs index 6e15169b20136..97f09fb13e7cd 100644 --- a/crates/transaction-generator-lib/src/publishing/raw_module_data.rs +++ b/crates/transaction-generator-lib/src/publishing/raw_module_data.rs @@ -19,27 +19,570 @@ use std::collections::HashMap; pub static PACKAGE_COMPLEX_METADATA: Lazy> = Lazy::new(|| { vec![ 7, 99, 111, 109, 112, 108, 101, 120, 1, 0, 0, 0, 0, 0, 0, 0, 0, 64, - 56, 52, 52, 69, 54, 50, 48, 54, 50, 52, 56, 68, 70, 67, 51, 69, 53, 51, - 49, 66, 48, 57, 55, 53, 55, 66, 56, 52, 54, 65, 66, 56, 51, 48, 69, 70, - 52, 55, 55, 48, 48, 68, 66, 49, 51, 50, 48, 68, 56, 66, 52, 55, 51, 54, - 54, 67, 54, 66, 52, 57, 66, 49, 67, 67, 131, 1, 31, 139, 8, 0, 0, 0, - 0, 0, 2, 255, 77, 139, 65, 10, 131, 48, 20, 68, 247, 255, 20, 193, 77, 86, - 141, 246, 0, 93, 116, 211, 75, 136, 139, 79, 156, 22, 49, 201, 15, 73, 177, 5, - 241, 238, 70, 80, 17, 102, 49, 51, 188, 215, 70, 182, 35, 127, 208, 81, 96, 15, - 245, 80, 218, 138, 143, 14, 127, 77, 19, 82, 30, 36, 108, 223, 221, 52, 166, 209, - 68, 109, 143, 136, 208, 35, 216, 1, 185, 163, 103, 252, 74, 126, 165, 34, 254, 36, - 141, 5, 156, 149, 19, 203, 174, 180, 202, 152, 250, 26, 222, 208, 155, 151, 9, 245, - 251, 16, 246, 243, 220, 149, 90, 136, 86, 76, 141, 120, 156, 145, 0, 0, 0, 2, - 19, 115, 109, 97, 114, 116, 95, 116, 97, 98, 108, 101, 95, 112, 105, 99, 116, 117, - 114, 101, 0, 0, 0, 14, 118, 101, 99, 116, 111, 114, 95, 112, 105, 99, 116, 117, - 114, 101, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 56, 53, 69, 57, 52, 54, 57, 66, 69, 66, 67, 49, 70, 70, 55, 57, 57, 57, + 48, 56, 54, 66, 68, 56, 70, 57, 65, 51, 57, 50, 67, 55, 65, 52, 67, 52, + 67, 56, 66, 57, 54, 50, 52, 52, 51, 52, 49, 68, 48, 57, 67, 57, 56, 69, + 53, 54, 67, 51, 69, 57, 69, 54, 52, 55, 156, 1, 31, 139, 8, 0, 0, 0, + 0, 0, 2, 255, 77, 141, 77, 14, 194, 32, 16, 133, 247, 156, 130, 116, 195, 74, + 138, 7, 112, 81, 53, 94, 162, 105, 12, 194, 168, 164, 192, 16, 70, 107, 19, 227, + 221, 133, 164, 154, 38, 179, 152, 247, 229, 253, 244, 73, 155, 81, 223, 96, 96, 81, + 7, 224, 59, 46, 12, 134, 228, 97, 22, 108, 130, 76, 14, 99, 101, 91, 169, 164, + 18, 140, 245, 22, 18, 68, 11, 209, 56, 160, 129, 117, 233, 129, 116, 202, 37, 248, + 194, 60, 22, 227, 155, 123, 52, 218, 151, 175, 145, 178, 93, 159, 174, 214, 77, 192, + 9, 218, 235, 47, 176, 192, 191, 110, 248, 167, 76, 104, 107, 51, 16, 213, 254, 244, + 188, 120, 71, 119, 200, 231, 5, 214, 98, 53, 119, 251, 195, 177, 97, 95, 93, 193, + 155, 66, 186, 0, 0, 0, 4, 14, 108, 105, 113, 117, 105, 100, 105, 116, 121, 95, + 112, 111, 111, 108, 0, 0, 0, 22, 108, 105, 113, 117, 105, 100, 105, 116, 121, 95, + 112, 111, 111, 108, 95, 119, 114, 97, 112, 112, 101, 114, 0, 0, 0, 19, 115, 109, + 97, 114, 116, 95, 116, 97, 98, 108, 101, 95, 112, 105, 99, 116, 117, 114, 101, 0, + 0, 0, 14, 118, 101, 99, 116, 111, 114, 95, 112, 105, 99, 116, 117, 114, 101, 0, + 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 14, + 65, 112, 116, 111, 115, 70, 114, 97, 109, 101, 119, 111, 114, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 14, 65, 112, 116, 111, 115, 70, 114, 97, 109, 101, 119, 111, 114, 107, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 11, 65, 112, 116, 111, 115, 83, 116, + 100, 108, 105, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 10, 77, 111, 118, 101, 83, 116, 100, 108, 105, 98, 0, + ] +}); + +#[rustfmt::skip] +pub static MODULE_COMPLEX_LIQUIDITY_POOL: Lazy> = Lazy::new(|| { + vec![ + 161, 28, 235, 11, 6, 0, 0, 0, 13, 1, 0, 30, 2, 30, 82, 3, 112, 181, + 3, 4, 165, 4, 86, 5, 251, 4, 226, 6, 7, 221, 11, 232, 12, 8, 197, 24, + 64, 6, 133, 25, 169, 1, 16, 174, 26, 149, 9, 10, 195, 35, 131, 1, 12, 198, + 36, 199, 23, 13, 141, 60, 38, 15, 179, 60, 2, 0, 1, 1, 2, 1, 3, 1, + 4, 1, 5, 1, 6, 1, 7, 1, 8, 1, 9, 1, 10, 1, 11, 1, 12, 1, + 13, 1, 14, 1, 15, 0, 16, 6, 0, 0, 17, 8, 0, 0, 18, 4, 0, 0, + 19, 8, 0, 0, 20, 8, 0, 0, 21, 6, 0, 7, 22, 7, 1, 0, 1, 4, + 24, 0, 0, 4, 27, 8, 0, 7, 29, 2, 0, 4, 31, 8, 0, 11, 55, 4, + 2, 0, 0, 0, 0, 4, 60, 6, 0, 4, 62, 6, 0, 4, 64, 6, 0, 12, + 70, 4, 1, 0, 0, 13, 86, 7, 0, 8, 93, 7, 1, 0, 0, 0, 23, 0, + 1, 0, 0, 25, 2, 3, 0, 0, 26, 4, 5, 0, 0, 28, 6, 7, 0, 0, + 30, 8, 9, 0, 0, 32, 10, 11, 1, 8, 0, 33, 12, 13, 0, 0, 34, 14, + 15, 0, 0, 35, 16, 0, 0, 0, 36, 7, 17, 0, 0, 1, 18, 7, 0, 0, + 37, 18, 19, 0, 0, 38, 18, 20, 0, 0, 39, 21, 22, 1, 8, 0, 40, 0, + 23, 0, 0, 41, 24, 0, 0, 0, 42, 21, 13, 1, 8, 0, 43, 7, 25, 0, + 0, 44, 26, 27, 0, 0, 45, 7, 23, 0, 0, 46, 0, 23, 0, 0, 47, 28, + 0, 0, 0, 48, 4, 0, 0, 12, 76, 30, 23, 1, 0, 12, 77, 31, 32, 1, + 0, 10, 78, 16, 19, 0, 7, 79, 35, 19, 1, 8, 11, 80, 37, 17, 2, 2, + 0, 11, 81, 38, 39, 2, 3, 0, 4, 82, 41, 27, 1, 8, 4, 83, 21, 42, + 1, 8, 4, 84, 21, 27, 1, 8, 11, 85, 45, 46, 2, 3, 0, 13, 87, 48, + 49, 0, 4, 88, 21, 49, 1, 8, 13, 89, 50, 0, 0, 13, 90, 51, 0, 0, + 1, 91, 32, 48, 1, 0, 14, 89, 53, 0, 1, 0, 7, 92, 54, 55, 0, 8, + 94, 0, 56, 1, 0, 9, 95, 57, 0, 0, 7, 96, 8, 58, 0, 7, 97, 8, + 21, 1, 8, 4, 98, 59, 11, 1, 8, 7, 99, 16, 55, 0, 11, 100, 0, 60, + 2, 7, 4, 7, 101, 21, 62, 2, 8, 8, 12, 102, 63, 0, 1, 4, 3, 103, + 65, 0, 1, 6, 4, 104, 8, 66, 0, 4, 105, 8, 67, 0, 4, 106, 8, 68, + 0, 9, 107, 10, 11, 1, 8, 9, 108, 10, 11, 1, 8, 4, 109, 21, 17, 1, + 8, 4, 110, 69, 0, 1, 8, 4, 111, 21, 23, 1, 8, 2, 112, 23, 23, 0, + 12, 100, 0, 72, 1, 4, 7, 113, 19, 21, 1, 8, 7, 114, 74, 19, 0, 4, + 115, 21, 75, 1, 8, 8, 116, 56, 65, 1, 0, 4, 117, 77, 42, 0, 4, 118, + 77, 23, 0, 5, 119, 22, 22, 0, 4, 120, 78, 0, 1, 8, 6, 121, 13, 23, + 0, 4, 122, 79, 0, 1, 8, 4, 41, 80, 27, 0, 4, 123, 81, 0, 1, 8, + 4, 124, 84, 27, 0, 4, 125, 87, 0, 1, 8, 9, 111, 10, 23, 1, 8, 11, + 77, 37, 46, 2, 2, 0, 11, 126, 89, 90, 2, 3, 2, 11, 127, 89, 0, 2, + 3, 2, 23, 7, 24, 7, 26, 34, 27, 36, 28, 36, 29, 40, 30, 40, 31, 43, + 32, 36, 34, 43, 26, 43, 37, 19, 38, 52, 37, 17, 40, 22, 43, 43, 44, 43, + 46, 36, 47, 61, 48, 7, 49, 64, 53, 65, 54, 65, 55, 40, 26, 65, 56, 40, + 57, 40, 59, 7, 60, 34, 62, 65, 63, 22, 5, 34, 62, 34, 67, 34, 69, 40, + 71, 40, 49, 85, 73, 40, 74, 34, 13, 34, 75, 36, 76, 36, 77, 36, 0, 1, + 10, 11, 6, 1, 8, 3, 3, 6, 12, 6, 12, 11, 6, 1, 8, 3, 2, 8, + 7, 8, 7, 2, 5, 11, 6, 1, 8, 3, 2, 4, 4, 4, 6, 12, 11, 6, + 1, 8, 8, 11, 6, 1, 8, 8, 1, 1, 11, 6, 1, 8, 3, 1, 6, 8, + 9, 1, 8, 2, 2, 5, 11, 6, 1, 9, 0, 1, 11, 6, 1, 8, 10, 3, + 11, 6, 1, 8, 3, 11, 6, 1, 8, 8, 3, 2, 3, 3, 3, 15, 15, 15, + 1, 15, 1, 6, 12, 1, 1, 3, 11, 6, 1, 8, 8, 11, 6, 1, 8, 8, + 1, 1, 5, 2, 1, 5, 1, 11, 6, 1, 9, 0, 1, 4, 1, 3, 4, 6, + 12, 8, 7, 8, 7, 1, 1, 10, 11, 6, 1, 8, 8, 3, 6, 12, 11, 6, + 1, 8, 3, 8, 7, 1, 8, 7, 4, 6, 12, 11, 6, 1, 8, 3, 5, 3, + 4, 6, 11, 15, 1, 11, 6, 1, 8, 3, 3, 3, 10, 11, 6, 1, 8, 3, + 1, 6, 11, 15, 1, 9, 0, 2, 6, 11, 15, 1, 9, 0, 3, 1, 6, 9, + 0, 11, 4, 4, 8, 7, 8, 7, 4, 4, 8, 7, 8, 7, 7, 8, 1, 5, + 6, 8, 3, 1, 8, 3, 1, 6, 11, 6, 1, 9, 0, 2, 5, 4, 2, 6, + 11, 11, 2, 9, 0, 9, 1, 9, 0, 2, 7, 11, 11, 2, 9, 0, 9, 1, + 9, 0, 1, 9, 1, 1, 8, 10, 3, 6, 12, 11, 6, 1, 9, 0, 3, 1, + 11, 6, 1, 8, 8, 1, 8, 8, 8, 4, 5, 6, 11, 11, 2, 5, 4, 4, + 5, 6, 11, 11, 2, 5, 4, 4, 6, 8, 1, 3, 6, 11, 11, 2, 9, 0, + 9, 1, 9, 0, 6, 9, 1, 1, 6, 9, 1, 40, 5, 11, 6, 1, 8, 10, + 8, 9, 11, 6, 1, 8, 10, 8, 9, 11, 6, 1, 8, 10, 8, 9, 11, 6, + 1, 8, 10, 6, 12, 7, 10, 2, 5, 7, 10, 2, 8, 9, 12, 3, 8, 2, + 8, 9, 7, 8, 4, 1, 1, 11, 6, 1, 8, 8, 6, 8, 9, 11, 6, 1, + 8, 3, 6, 8, 9, 6, 12, 6, 12, 10, 2, 10, 2, 11, 6, 1, 8, 8, + 11, 6, 1, 8, 8, 11, 6, 1, 8, 8, 11, 6, 1, 8, 8, 11, 6, 1, + 8, 8, 11, 6, 1, 8, 8, 11, 6, 1, 8, 8, 11, 6, 1, 8, 8, 11, + 6, 1, 8, 8, 11, 6, 1, 8, 8, 8, 16, 8, 16, 1, 10, 2, 1, 8, + 16, 2, 7, 8, 16, 8, 16, 2, 7, 8, 16, 10, 2, 1, 2, 2, 7, 10, + 9, 0, 10, 9, 0, 2, 6, 12, 10, 2, 1, 8, 9, 1, 11, 17, 1, 9, + 0, 7, 6, 8, 9, 11, 17, 1, 4, 8, 16, 8, 16, 2, 8, 16, 8, 16, + 1, 12, 2, 6, 8, 9, 11, 6, 1, 9, 0, 1, 11, 11, 2, 9, 0, 9, + 1, 2, 8, 8, 8, 3, 1, 11, 6, 1, 9, 1, 2, 7, 11, 15, 1, 9, + 0, 9, 0, 1, 8, 0, 1, 9, 0, 1, 8, 12, 1, 8, 13, 1, 8, 14, + 3, 6, 8, 14, 11, 6, 1, 9, 0, 1, 18, 15, 15, 15, 15, 3, 15, 3, + 3, 3, 15, 6, 8, 3, 6, 8, 3, 15, 15, 15, 15, 15, 15, 11, 15, 15, + 3, 15, 15, 15, 15, 15, 15, 15, 15, 1, 11, 15, 1, 9, 0, 10, 5, 7, + 10, 2, 5, 7, 10, 2, 5, 6, 5, 1, 10, 2, 11, 6, 1, 8, 8, 11, + 6, 1, 8, 8, 2, 6, 5, 10, 2, 1, 11, 17, 1, 4, 26, 1, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 11, 6, 1, 8, 10, 4, 8, 7, 6, 8, + 13, 11, 6, 1, 8, 3, 6, 8, 3, 3, 3, 11, 6, 1, 8, 10, 11, 6, + 1, 8, 10, 11, 6, 1, 8, 8, 3, 11, 6, 1, 8, 8, 3, 3, 1, 6, + 8, 7, 3, 6, 8, 13, 11, 6, 1, 9, 0, 3, 2, 11, 6, 1, 9, 0, + 8, 7, 2, 6, 8, 13, 3, 3, 6, 8, 14, 11, 6, 1, 9, 0, 8, 7, + 1, 6, 8, 3, 22, 15, 8, 7, 15, 3, 3, 8, 7, 7, 8, 1, 3, 4, + 11, 6, 1, 8, 8, 15, 15, 8, 7, 6, 8, 3, 6, 8, 3, 6, 8, 3, + 15, 15, 15, 15, 11, 6, 1, 8, 10, 11, 6, 1, 8, 10, 2, 7, 8, 7, + 3, 1, 8, 5, 3, 5, 11, 6, 1, 8, 10, 11, 6, 1, 8, 10, 4, 6, + 8, 14, 11, 6, 1, 9, 0, 11, 6, 1, 9, 0, 3, 19, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 7, 8, 1, 4, 4, 4, 4, 7, 4, 7, + 4, 3, 7, 11, 11, 2, 9, 0, 9, 1, 9, 0, 9, 1, 1, 7, 9, 1, + 22, 108, 105, 113, 117, 105, 100, 105, 116, 121, 95, 112, 111, 111, 108, 95, 119, 114, + 97, 112, 112, 101, 114, 14, 108, 105, 113, 117, 105, 100, 105, 116, 121, 95, 112, 111, + 111, 108, 3, 98, 99, 115, 5, 101, 114, 114, 111, 114, 5, 101, 118, 101, 110, 116, + 14, 102, 117, 110, 103, 105, 98, 108, 101, 95, 97, 115, 115, 101, 116, 7, 109, 97, + 116, 104, 49, 50, 56, 6, 109, 97, 116, 104, 54, 52, 6, 111, 98, 106, 101, 99, + 116, 6, 111, 112, 116, 105, 111, 110, 22, 112, 114, 105, 109, 97, 114, 121, 95, 102, + 117, 110, 103, 105, 98, 108, 101, 95, 115, 116, 111, 114, 101, 6, 115, 105, 103, 110, + 101, 114, 11, 115, 109, 97, 114, 116, 95, 116, 97, 98, 108, 101, 12, 115, 109, 97, + 114, 116, 95, 118, 101, 99, 116, 111, 114, 6, 115, 116, 114, 105, 110, 103, 6, 118, + 101, 99, 116, 111, 114, 10, 67, 114, 101, 97, 116, 101, 80, 111, 111, 108, 14, 70, + 101, 101, 115, 65, 99, 99, 111, 117, 110, 116, 105, 110, 103, 11, 76, 80, 84, 111, + 107, 101, 110, 82, 101, 102, 115, 13, 76, 105, 113, 117, 105, 100, 105, 116, 121, 80, + 111, 111, 108, 20, 76, 105, 113, 117, 105, 100, 105, 116, 121, 80, 111, 111, 108, 67, + 111, 110, 102, 105, 103, 115, 4, 83, 119, 97, 112, 6, 79, 98, 106, 101, 99, 116, + 9, 97, 108, 108, 95, 112, 111, 111, 108, 115, 13, 70, 117, 110, 103, 105, 98, 108, + 101, 65, 115, 115, 101, 116, 10, 99, 108, 97, 105, 109, 95, 102, 101, 101, 115, 14, + 99, 108, 97, 105, 109, 97, 98, 108, 101, 95, 102, 101, 101, 115, 8, 77, 101, 116, + 97, 100, 97, 116, 97, 6, 99, 114, 101, 97, 116, 101, 14, 67, 111, 110, 115, 116, + 114, 117, 99, 116, 111, 114, 82, 101, 102, 20, 99, 114, 101, 97, 116, 101, 95, 108, + 112, 95, 116, 111, 107, 101, 110, 95, 114, 101, 102, 115, 13, 70, 117, 110, 103, 105, + 98, 108, 101, 83, 116, 111, 114, 101, 21, 101, 110, 115, 117, 114, 101, 95, 108, 112, + 95, 116, 111, 107, 101, 110, 95, 115, 116, 111, 114, 101, 14, 103, 101, 116, 95, 97, + 109, 111, 117, 110, 116, 95, 111, 117, 116, 5, 103, 101, 116, 95, 121, 11, 105, 110, + 105, 116, 95, 109, 111, 100, 117, 108, 101, 9, 105, 115, 95, 115, 116, 97, 98, 108, + 101, 22, 108, 105, 113, 117, 105, 100, 105, 116, 121, 95, 112, 111, 111, 108, 95, 97, + 100, 100, 114, 101, 115, 115, 27, 108, 105, 113, 117, 105, 100, 105, 116, 121, 95, 112, + 111, 111, 108, 95, 97, 100, 100, 114, 101, 115, 115, 95, 115, 97, 102, 101, 15, 108, + 112, 95, 116, 111, 107, 101, 110, 95, 115, 117, 112, 112, 108, 121, 13, 109, 105, 110, + 95, 108, 105, 113, 117, 105, 100, 105, 116, 121, 4, 109, 105, 110, 116, 13, 112, 111, + 111, 108, 95, 114, 101, 115, 101, 114, 118, 101, 115, 22, 115, 117, 112, 112, 111, 114, + 116, 101, 100, 95, 105, 110, 110, 101, 114, 95, 97, 115, 115, 101, 116, 115, 4, 115, + 119, 97, 112, 12, 115, 119, 97, 112, 95, 102, 101, 101, 95, 98, 112, 115, 21, 116, + 111, 116, 97, 108, 95, 110, 117, 109, 98, 101, 114, 95, 111, 102, 95, 112, 111, 111, + 108, 115, 8, 116, 114, 97, 110, 115, 102, 101, 114, 21, 117, 112, 100, 97, 116, 101, + 95, 99, 108, 97, 105, 109, 97, 98, 108, 101, 95, 102, 101, 101, 115, 4, 112, 111, + 111, 108, 7, 116, 111, 107, 101, 110, 95, 49, 7, 116, 111, 107, 101, 110, 95, 50, + 12, 116, 111, 116, 97, 108, 95, 102, 101, 101, 115, 95, 49, 12, 116, 111, 116, 97, + 108, 95, 102, 101, 101, 115, 95, 50, 26, 116, 111, 116, 97, 108, 95, 102, 101, 101, + 115, 95, 97, 116, 95, 108, 97, 115, 116, 95, 99, 108, 97, 105, 109, 95, 49, 10, + 83, 109, 97, 114, 116, 84, 97, 98, 108, 101, 26, 116, 111, 116, 97, 108, 95, 102, + 101, 101, 115, 95, 97, 116, 95, 108, 97, 115, 116, 95, 99, 108, 97, 105, 109, 95, + 50, 11, 99, 108, 97, 105, 109, 97, 98, 108, 101, 95, 49, 11, 99, 108, 97, 105, + 109, 97, 98, 108, 101, 95, 50, 8, 98, 117, 114, 110, 95, 114, 101, 102, 7, 66, + 117, 114, 110, 82, 101, 102, 8, 109, 105, 110, 116, 95, 114, 101, 102, 7, 77, 105, + 110, 116, 82, 101, 102, 12, 116, 114, 97, 110, 115, 102, 101, 114, 95, 114, 101, 102, + 11, 84, 114, 97, 110, 115, 102, 101, 114, 82, 101, 102, 13, 116, 111, 107, 101, 110, + 95, 115, 116, 111, 114, 101, 95, 49, 13, 116, 111, 107, 101, 110, 95, 115, 116, 111, + 114, 101, 95, 50, 12, 102, 101, 101, 115, 95, 115, 116, 111, 114, 101, 95, 49, 12, + 102, 101, 101, 115, 95, 115, 116, 111, 114, 101, 95, 50, 13, 108, 112, 95, 116, 111, + 107, 101, 110, 95, 114, 101, 102, 115, 11, 83, 109, 97, 114, 116, 86, 101, 99, 116, + 111, 114, 9, 105, 115, 95, 112, 97, 117, 115, 101, 100, 14, 115, 116, 97, 98, 108, + 101, 95, 102, 101, 101, 95, 98, 112, 115, 16, 118, 111, 108, 97, 116, 105, 108, 101, + 95, 102, 101, 101, 95, 98, 112, 115, 10, 102, 114, 111, 109, 95, 116, 111, 107, 101, + 110, 9, 97, 109, 111, 117, 110, 116, 95, 105, 110, 6, 108, 101, 110, 103, 116, 104, + 6, 98, 111, 114, 114, 111, 119, 10, 97, 100, 100, 114, 101, 115, 115, 95, 111, 102, + 14, 111, 98, 106, 101, 99, 116, 95, 97, 100, 100, 114, 101, 115, 115, 8, 99, 111, + 110, 116, 97, 105, 110, 115, 6, 114, 101, 109, 111, 118, 101, 8, 119, 105, 116, 104, + 100, 114, 97, 119, 14, 115, 116, 111, 114, 101, 95, 109, 101, 116, 97, 100, 97, 116, + 97, 4, 122, 101, 114, 111, 19, 98, 111, 114, 114, 111, 119, 95, 119, 105, 116, 104, + 95, 100, 101, 102, 97, 117, 108, 116, 6, 83, 116, 114, 105, 110, 103, 4, 117, 116, + 102, 56, 6, 115, 121, 109, 98, 111, 108, 6, 97, 112, 112, 101, 110, 100, 11, 97, + 112, 112, 101, 110, 100, 95, 117, 116, 102, 56, 8, 116, 111, 95, 98, 121, 116, 101, + 115, 19, 99, 114, 101, 97, 116, 101, 95, 110, 97, 109, 101, 100, 95, 111, 98, 106, + 101, 99, 116, 6, 79, 112, 116, 105, 111, 110, 4, 110, 111, 110, 101, 43, 99, 114, + 101, 97, 116, 101, 95, 112, 114, 105, 109, 97, 114, 121, 95, 115, 116, 111, 114, 101, + 95, 101, 110, 97, 98, 108, 101, 100, 95, 102, 117, 110, 103, 105, 98, 108, 101, 95, + 97, 115, 115, 101, 116, 15, 103, 101, 110, 101, 114, 97, 116, 101, 95, 115, 105, 103, + 110, 101, 114, 27, 111, 98, 106, 101, 99, 116, 95, 102, 114, 111, 109, 95, 99, 111, + 110, 115, 116, 114, 117, 99, 116, 111, 114, 95, 114, 101, 102, 12, 99, 114, 101, 97, + 116, 101, 95, 115, 116, 111, 114, 101, 25, 99, 114, 101, 97, 116, 101, 95, 111, 98, + 106, 101, 99, 116, 95, 102, 114, 111, 109, 95, 111, 98, 106, 101, 99, 116, 3, 110, + 101, 119, 7, 99, 111, 110, 118, 101, 114, 116, 9, 112, 117, 115, 104, 95, 98, 97, + 99, 107, 4, 101, 109, 105, 116, 17, 103, 101, 110, 101, 114, 97, 116, 101, 95, 98, + 117, 114, 110, 95, 114, 101, 102, 17, 103, 101, 110, 101, 114, 97, 116, 101, 95, 109, + 105, 110, 116, 95, 114, 101, 102, 21, 103, 101, 110, 101, 114, 97, 116, 101, 95, 116, + 114, 97, 110, 115, 102, 101, 114, 95, 114, 101, 102, 27, 101, 110, 115, 117, 114, 101, + 95, 112, 114, 105, 109, 97, 114, 121, 95, 115, 116, 111, 114, 101, 95, 101, 120, 105, + 115, 116, 115, 13, 112, 114, 105, 109, 97, 114, 121, 95, 115, 116, 111, 114, 101, 9, + 105, 115, 95, 102, 114, 111, 122, 101, 110, 15, 115, 101, 116, 95, 102, 114, 111, 122, + 101, 110, 95, 102, 108, 97, 103, 7, 98, 97, 108, 97, 110, 99, 101, 16, 105, 110, + 118, 97, 108, 105, 100, 95, 97, 114, 103, 117, 109, 101, 110, 116, 17, 97, 100, 100, + 114, 101, 115, 115, 95, 116, 111, 95, 111, 98, 106, 101, 99, 116, 21, 99, 114, 101, + 97, 116, 101, 95, 111, 98, 106, 101, 99, 116, 95, 97, 100, 100, 114, 101, 115, 115, + 6, 115, 117, 112, 112, 108, 121, 12, 100, 101, 115, 116, 114, 111, 121, 95, 115, 111, + 109, 101, 19, 109, 101, 116, 97, 100, 97, 116, 97, 95, 102, 114, 111, 109, 95, 97, + 115, 115, 101, 116, 6, 97, 109, 111, 117, 110, 116, 4, 115, 113, 114, 116, 7, 109, + 105, 110, 116, 95, 116, 111, 3, 109, 105, 110, 7, 100, 101, 112, 111, 115, 105, 116, + 16, 100, 101, 112, 111, 115, 105, 116, 95, 119, 105, 116, 104, 95, 114, 101, 102, 7, + 101, 120, 116, 114, 97, 99, 116, 17, 116, 114, 97, 110, 115, 102, 101, 114, 95, 119, + 105, 116, 104, 95, 114, 101, 102, 23, 98, 111, 114, 114, 111, 119, 95, 109, 117, 116, + 95, 119, 105, 116, 104, 95, 100, 101, 102, 97, 117, 108, 116, 6, 117, 112, 115, 101, + 114, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 205, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 8, 4, 0, 0, 0, + 0, 0, 0, 0, 3, 8, 2, 0, 0, 0, 0, 0, 0, 0, 3, 8, 3, 0, + 0, 0, 0, 0, 0, 0, 3, 8, 8, 0, 0, 0, 0, 0, 0, 0, 3, 8, + 6, 0, 0, 0, 0, 0, 0, 0, 3, 8, 5, 0, 0, 0, 0, 0, 0, 0, + 3, 8, 7, 0, 0, 0, 0, 0, 0, 0, 3, 8, 1, 0, 0, 0, 0, 0, + 0, 0, 3, 8, 16, 39, 0, 0, 0, 0, 0, 0, 2, 1, 8, 3, 8, 25, + 0, 0, 0, 0, 0, 0, 0, 3, 8, 232, 3, 0, 0, 0, 0, 0, 0, 5, + 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 205, 10, 2, 4, + 3, 76, 80, 45, 10, 2, 2, 1, 45, 10, 2, 1, 0, 10, 2, 3, 2, 76, + 80, 18, 97, 112, 116, 111, 115, 58, 58, 109, 101, 116, 97, 100, 97, 116, 97, 95, + 118, 49, 128, 9, 8, 1, 0, 0, 0, 0, 0, 0, 0, 12, 69, 90, 69, 82, + 79, 95, 65, 77, 79, 85, 78, 84, 52, 65, 109, 111, 117, 110, 116, 32, 111, 102, + 32, 116, 111, 107, 101, 110, 115, 32, 112, 114, 111, 118, 105, 100, 101, 100, 32, 109, + 117, 115, 116, 32, 98, 101, 32, 103, 114, 101, 97, 116, 101, 114, 32, 116, 104, 97, + 110, 32, 122, 101, 114, 111, 46, 2, 0, 0, 0, 0, 0, 0, 0, 30, 69, 73, + 78, 83, 85, 70, 70, 73, 67, 73, 69, 78, 84, 95, 76, 73, 81, 85, 73, 68, + 73, 84, 89, 95, 77, 73, 78, 84, 69, 68, 99, 84, 104, 101, 32, 97, 109, 111, + 117, 110, 116, 32, 111, 102, 32, 108, 105, 113, 117, 105, 100, 105, 116, 121, 32, 112, + 114, 111, 118, 105, 100, 101, 100, 32, 105, 115, 32, 115, 111, 32, 115, 109, 97, 108, + 108, 32, 116, 104, 97, 116, 32, 99, 111, 114, 114, 101, 115, 112, 111, 110, 100, 105, + 110, 103, 32, 76, 80, 32, 116, 111, 107, 101, 110, 32, 97, 109, 111, 117, 110, 116, + 32, 105, 115, 32, 114, 111, 117, 110, 100, 101, 100, 32, 116, 111, 32, 122, 101, 114, + 111, 46, 3, 0, 0, 0, 0, 0, 0, 0, 32, 69, 73, 78, 83, 85, 70, 70, + 73, 67, 73, 69, 78, 84, 95, 76, 73, 81, 85, 73, 68, 73, 84, 89, 95, 82, + 69, 68, 69, 69, 77, 69, 68, 98, 65, 109, 111, 117, 110, 116, 32, 111, 102, 32, + 76, 80, 32, 116, 111, 107, 101, 110, 115, 32, 114, 101, 100, 101, 101, 109, 101, 100, + 32, 105, 115, 32, 116, 111, 111, 32, 115, 109, 97, 108, 108, 44, 32, 115, 111, 32, + 97, 109, 111, 117, 110, 116, 115, 32, 111, 102, 32, 116, 111, 107, 101, 110, 115, 32, + 114, 101, 99, 101, 105, 118, 101, 100, 32, 98, 97, 99, 107, 32, 97, 114, 101, 32, + 114, 111, 117, 110, 100, 101, 100, 32, 116, 111, 32, 122, 101, 114, 111, 46, 4, 0, + 0, 0, 0, 0, 0, 0, 22, 69, 73, 78, 67, 79, 82, 82, 69, 67, 84, 95, + 83, 87, 65, 80, 95, 65, 77, 79, 85, 78, 84, 94, 84, 104, 101, 32, 115, 112, + 101, 99, 105, 102, 105, 101, 100, 32, 97, 109, 111, 117, 110, 116, 32, 111, 102, 32, + 111, 117, 116, 112, 117, 116, 32, 116, 111, 107, 101, 110, 115, 32, 105, 115, 32, 105, + 110, 99, 111, 114, 114, 101, 99, 116, 32, 97, 110, 100, 32, 100, 111, 101, 115, 32, + 110, 111, 116, 32, 109, 97, 105, 110, 116, 97, 105, 110, 32, 116, 104, 101, 32, 112, + 111, 111, 108, 39, 115, 32, 105, 110, 118, 97, 114, 105, 97, 110, 116, 46, 5, 0, + 0, 0, 0, 0, 0, 0, 16, 69, 78, 79, 84, 95, 83, 84, 79, 82, 69, 95, + 79, 87, 78, 69, 82, 50, 84, 104, 101, 32, 99, 97, 108, 108, 101, 114, 32, 105, + 115, 32, 110, 111, 116, 32, 116, 104, 101, 32, 111, 119, 110, 101, 114, 32, 111, 102, + 32, 116, 104, 101, 32, 76, 80, 32, 116, 111, 107, 101, 110, 32, 115, 116, 111, 114, + 101, 46, 6, 0, 0, 0, 0, 0, 0, 0, 15, 69, 78, 79, 84, 95, 65, 85, + 84, 72, 79, 82, 73, 90, 69, 68, 50, 67, 108, 97, 108, 101, 114, 32, 105, 115, + 32, 110, 111, 116, 32, 97, 117, 116, 104, 111, 114, 105, 122, 101, 100, 32, 116, 111, + 32, 112, 101, 114, 102, 111, 114, 109, 32, 116, 104, 101, 32, 111, 112, 101, 114, 97, + 116, 105, 111, 110, 46, 7, 0, 0, 0, 0, 0, 0, 0, 17, 69, 83, 87, 65, + 80, 83, 95, 65, 82, 69, 95, 80, 65, 85, 83, 69, 68, 31, 65, 108, 108, 32, + 115, 119, 97, 112, 115, 32, 97, 114, 101, 32, 99, 117, 114, 114, 101, 110, 116, 108, + 121, 32, 112, 97, 117, 115, 101, 100, 46, 8, 0, 0, 0, 0, 0, 0, 0, 41, + 69, 75, 95, 66, 69, 70, 79, 82, 69, 95, 83, 87, 65, 80, 95, 71, 82, 69, + 65, 84, 69, 82, 95, 84, 72, 65, 78, 95, 69, 75, 95, 65, 70, 84, 69, 82, + 95, 83, 87, 65, 80, 46, 83, 119, 97, 112, 32, 108, 101, 97, 118, 101, 115, 32, + 112, 111, 111, 108, 32, 105, 110, 32, 97, 32, 119, 111, 114, 115, 101, 32, 115, 116, + 97, 116, 101, 32, 116, 104, 97, 110, 32, 98, 101, 102, 111, 114, 101, 46, 4, 4, + 83, 119, 97, 112, 1, 4, 0, 10, 67, 114, 101, 97, 116, 101, 80, 111, 111, 108, + 1, 4, 0, 13, 76, 105, 113, 117, 105, 100, 105, 116, 121, 80, 111, 111, 108, 1, + 3, 1, 24, 48, 120, 49, 58, 58, 111, 98, 106, 101, 99, 116, 58, 58, 79, 98, + 106, 101, 99, 116, 71, 114, 111, 117, 112, 14, 70, 101, 101, 115, 65, 99, 99, 111, + 117, 110, 116, 105, 110, 103, 1, 3, 1, 24, 48, 120, 49, 58, 58, 111, 98, 106, + 101, 99, 116, 58, 58, 79, 98, 106, 101, 99, 116, 71, 114, 111, 117, 112, 13, 9, + 97, 108, 108, 95, 112, 111, 111, 108, 115, 1, 1, 0, 9, 105, 115, 95, 115, 116, + 97, 98, 108, 101, 1, 1, 0, 12, 115, 119, 97, 112, 95, 102, 101, 101, 95, 98, + 112, 115, 1, 1, 0, 13, 109, 105, 110, 95, 108, 105, 113, 117, 105, 100, 105, 116, + 121, 1, 1, 0, 13, 112, 111, 111, 108, 95, 114, 101, 115, 101, 114, 118, 101, 115, + 1, 1, 0, 14, 99, 108, 97, 105, 109, 97, 98, 108, 101, 95, 102, 101, 101, 115, + 1, 1, 0, 14, 103, 101, 116, 95, 97, 109, 111, 117, 110, 116, 95, 111, 117, 116, + 1, 1, 0, 14, 108, 105, 113, 117, 105, 100, 105, 116, 121, 95, 112, 111, 111, 108, + 1, 1, 0, 15, 108, 112, 95, 116, 111, 107, 101, 110, 95, 115, 117, 112, 112, 108, + 121, 1, 1, 0, 21, 116, 111, 116, 97, 108, 95, 110, 117, 109, 98, 101, 114, 95, + 111, 102, 95, 112, 111, 111, 108, 115, 1, 1, 0, 22, 108, 105, 113, 117, 105, 100, + 105, 116, 121, 95, 112, 111, 111, 108, 95, 97, 100, 100, 114, 101, 115, 115, 1, 1, + 0, 22, 115, 117, 112, 112, 111, 114, 116, 101, 100, 95, 105, 110, 110, 101, 114, 95, + 97, 115, 115, 101, 116, 115, 1, 1, 0, 27, 108, 105, 113, 117, 105, 100, 105, 116, + 121, 95, 112, 111, 111, 108, 95, 97, 100, 100, 114, 101, 115, 115, 95, 115, 97, 102, + 101, 1, 1, 0, 0, 2, 4, 49, 11, 6, 1, 8, 3, 50, 11, 6, 1, 8, + 8, 51, 11, 6, 1, 8, 8, 36, 1, 1, 2, 6, 52, 4, 53, 4, 54, 11, + 11, 2, 5, 4, 56, 11, 11, 2, 5, 4, 57, 11, 11, 2, 5, 4, 58, 11, + 11, 2, 5, 4, 2, 2, 3, 59, 8, 12, 61, 8, 13, 63, 8, 14, 3, 2, + 7, 65, 11, 6, 1, 8, 10, 66, 11, 6, 1, 8, 10, 67, 11, 6, 1, 8, + 10, 68, 11, 6, 1, 8, 10, 69, 8, 2, 45, 3, 36, 1, 4, 2, 4, 23, + 11, 15, 1, 11, 6, 1, 8, 3, 71, 1, 72, 3, 73, 3, 5, 2, 3, 49, + 5, 74, 11, 6, 1, 8, 8, 75, 3, 0, 1, 0, 1, 4, 29, 31, 7, 12, + 43, 4, 16, 0, 12, 0, 64, 7, 0, 0, 0, 0, 0, 0, 0, 0, 12, 3, + 10, 0, 56, 0, 12, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 12, 1, 10, + 1, 10, 2, 35, 4, 27, 5, 16, 13, 3, 10, 0, 10, 1, 56, 1, 20, 68, + 7, 11, 1, 6, 1, 0, 0, 0, 0, 0, 0, 0, 22, 12, 1, 5, 11, 11, + 0, 1, 11, 3, 2, 1, 3, 0, 2, 1, 3, 33, 93, 11, 1, 17, 25, 12, + 12, 10, 12, 10, 2, 17, 22, 14, 2, 56, 2, 43, 3, 12, 13, 14, 2, 56, + 2, 42, 1, 12, 11, 10, 11, 16, 1, 10, 12, 56, 3, 4, 25, 10, 11, 15, + 1, 10, 12, 56, 4, 12, 3, 5, 27, 50, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 12, 3, 11, 3, 12, 7, 10, 11, 16, 2, + 10, 12, 56, 3, 4, 40, 11, 11, 15, 2, 11, 12, 56, 4, 12, 4, 5, 44, + 11, 11, 1, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 12, 4, 11, 4, 12, 8, 10, 7, 50, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 4, 59, 10, 0, 10, 13, 16, 3, + 20, 11, 7, 52, 56, 5, 12, 5, 5, 65, 10, 13, 16, 3, 20, 56, 6, 56, + 7, 12, 5, 11, 5, 12, 9, 10, 8, 50, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 36, 4, 80, 11, 0, 11, 13, 16, 4, 20, + 11, 8, 52, 56, 5, 12, 6, 5, 88, 11, 0, 1, 11, 13, 16, 4, 20, 56, + 6, 56, 7, 12, 6, 11, 6, 12, 10, 11, 9, 11, 10, 2, 2, 1, 0, 1, + 1, 44, 31, 14, 1, 56, 2, 43, 1, 12, 9, 10, 9, 16, 1, 12, 7, 10, + 0, 12, 6, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 12, 5, 11, 7, 11, 6, 14, 5, 56, 8, 20, 12, 8, 11, 9, 16, + 2, 12, 4, 11, 0, 12, 3, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 12, 2, 11, 8, 11, 4, 11, 3, 14, 2, 56, 8, + 20, 2, 3, 1, 0, 1, 4, 47, 180, 1, 7, 12, 42, 4, 12, 21, 11, 0, + 10, 1, 10, 2, 10, 3, 12, 22, 12, 39, 12, 36, 12, 29, 10, 36, 10, 39, + 12, 40, 12, 37, 7, 13, 17, 33, 12, 43, 13, 43, 11, 37, 56, 9, 17, 35, + 13, 43, 7, 14, 17, 36, 13, 43, 11, 40, 56, 9, 17, 35, 11, 43, 12, 42, + 11, 36, 11, 39, 11, 22, 12, 23, 12, 41, 12, 38, 7, 15, 12, 31, 13, 31, + 12, 13, 14, 38, 56, 10, 12, 4, 11, 13, 14, 4, 56, 11, 56, 12, 13, 31, + 12, 15, 14, 41, 56, 10, 12, 14, 11, 15, 14, 14, 56, 11, 56, 12, 13, 31, + 14, 23, 56, 13, 56, 12, 11, 31, 12, 30, 11, 29, 11, 30, 17, 39, 12, 16, + 14, 16, 12, 25, 10, 25, 56, 14, 11, 42, 7, 16, 17, 33, 7, 9, 7, 15, + 17, 33, 7, 15, 17, 33, 17, 41, 11, 25, 12, 27, 10, 27, 17, 42, 12, 17, + 14, 17, 12, 28, 10, 27, 56, 15, 12, 24, 10, 27, 10, 24, 56, 16, 1, 10, + 28, 12, 12, 10, 28, 10, 1, 12, 34, 17, 45, 12, 10, 14, 10, 11, 34, 56, + 16, 12, 11, 10, 28, 10, 2, 12, 35, 17, 45, 12, 8, 14, 8, 11, 35, 56, + 16, 12, 9, 10, 28, 10, 1, 12, 32, 17, 45, 12, 6, 14, 6, 11, 32, 56, + 16, 12, 7, 10, 28, 10, 2, 12, 33, 17, 45, 12, 20, 14, 20, 11, 33, 56, + 16, 12, 5, 11, 27, 17, 4, 12, 19, 10, 3, 4, 142, 1, 10, 21, 16, 5, + 20, 12, 18, 5, 146, 1, 10, 21, 16, 6, 20, 12, 18, 11, 12, 11, 11, 11, + 9, 11, 7, 11, 5, 11, 19, 11, 18, 10, 3, 18, 3, 45, 3, 11, 28, 50, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 17, 56, + 17, 56, 17, 56, 17, 18, 1, 45, 1, 11, 24, 56, 18, 12, 26, 11, 21, 15, + 0, 10, 26, 56, 19, 10, 26, 11, 1, 11, 2, 11, 3, 18, 0, 56, 20, 11, + 26, 2, 4, 0, 0, 0, 0, 8, 10, 0, 17, 50, 10, 0, 17, 51, 11, 0, + 17, 52, 18, 2, 2, 5, 0, 0, 1, 3, 11, 22, 10, 0, 10, 1, 56, 21, + 1, 11, 0, 10, 1, 56, 22, 12, 2, 10, 2, 56, 23, 32, 4, 20, 14, 1, + 56, 24, 43, 3, 16, 7, 16, 8, 10, 2, 8, 56, 25, 11, 2, 2, 6, 1, + 0, 1, 3, 70, 138, 1, 14, 0, 56, 2, 43, 3, 12, 14, 10, 14, 16, 9, + 20, 56, 26, 77, 12, 17, 10, 14, 16, 10, 20, 56, 26, 77, 12, 18, 11, 1, + 10, 14, 16, 9, 20, 56, 6, 33, 4, 28, 11, 17, 11, 18, 12, 4, 12, 3, + 5, 32, 11, 18, 11, 17, 12, 4, 12, 3, 11, 3, 11, 4, 12, 20, 12, 19, + 10, 2, 10, 14, 16, 11, 20, 7, 8, 12, 10, 12, 9, 12, 7, 10, 10, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 34, 4, 49, 5, 54, 11, 14, 1, 6, 4, + 0, 0, 0, 0, 0, 0, 0, 17, 58, 39, 11, 7, 53, 11, 9, 53, 24, 11, + 10, 53, 26, 52, 12, 11, 11, 2, 10, 11, 23, 77, 12, 8, 10, 14, 16, 12, + 20, 4, 124, 11, 14, 12, 13, 10, 13, 16, 9, 20, 56, 26, 77, 12, 15, 10, + 13, 16, 10, 20, 56, 26, 77, 12, 16, 11, 13, 16, 12, 20, 4, 108, 10, 15, + 10, 15, 24, 10, 15, 24, 10, 16, 24, 10, 16, 10, 16, 24, 11, 16, 24, 11, + 15, 24, 22, 12, 5, 5, 112, 11, 15, 11, 16, 24, 12, 5, 11, 5, 12, 12, + 10, 20, 11, 8, 11, 19, 22, 11, 12, 11, 20, 17, 7, 23, 12, 6, 5, 134, + 1, 11, 14, 1, 10, 8, 11, 20, 24, 11, 19, 11, 8, 22, 26, 12, 6, 11, + 6, 52, 11, 11, 2, 7, 0, 0, 0, 71, 114, 6, 0, 0, 0, 0, 0, 0, + 0, 0, 12, 5, 10, 5, 6, 255, 0, 0, 0, 0, 0, 0, 0, 35, 4, 112, + 5, 7, 10, 2, 12, 13, 10, 0, 10, 2, 12, 10, 12, 7, 10, 7, 10, 10, + 10, 10, 24, 10, 10, 24, 24, 10, 7, 10, 7, 24, 11, 7, 24, 11, 10, 24, + 22, 12, 6, 10, 6, 10, 1, 35, 4, 60, 10, 0, 10, 2, 12, 11, 12, 8, + 10, 1, 11, 6, 23, 74, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 10, 8, 24, 10, 11, 11, 11, 24, 24, 10, 8, 10, 8, 24, 11, 8, + 24, 22, 26, 12, 3, 11, 2, 11, 3, 22, 12, 2, 5, 86, 10, 0, 10, 2, + 12, 12, 12, 9, 11, 6, 10, 1, 23, 74, 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 10, 9, 24, 10, 12, 11, 12, 24, 24, 10, 9, 10, + 9, 24, 11, 9, 24, 22, 26, 12, 4, 11, 2, 11, 4, 23, 12, 2, 10, 2, + 10, 13, 36, 4, 99, 10, 2, 11, 13, 23, 74, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 11, 65, 112, 116, 111, - 115, 83, 116, 100, 108, 105, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 37, 4, 98, 11, 2, 2, 5, 107, 11, 13, 10, + 2, 23, 74, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, + 4, 107, 11, 2, 2, 11, 5, 6, 1, 0, 0, 0, 0, 0, 0, 0, 22, 12, + 5, 5, 2, 11, 2, 2, 8, 0, 0, 0, 0, 8, 11, 0, 56, 27, 9, 6, + 10, 0, 0, 0, 0, 0, 0, 0, 6, 20, 0, 0, 0, 0, 0, 0, 0, 18, + 4, 45, 4, 2, 9, 1, 0, 1, 3, 0, 6, 14, 0, 56, 2, 43, 3, 16, + 12, 20, 2, 10, 1, 0, 0, 0, 6, 11, 0, 11, 1, 11, 2, 17, 11, 56, + 28, 2, 11, 1, 0, 0, 73, 38, 7, 12, 12, 7, 14, 7, 12, 8, 11, 0, + 11, 1, 11, 2, 12, 9, 12, 12, 12, 11, 7, 15, 12, 10, 13, 10, 12, 4, + 14, 11, 56, 10, 12, 3, 11, 4, 14, 3, 56, 11, 56, 12, 13, 10, 12, 6, + 14, 12, 56, 10, 12, 5, 11, 6, 14, 5, 56, 11, 56, 12, 13, 10, 14, 9, + 56, 13, 56, 12, 11, 8, 11, 10, 17, 61, 2, 12, 1, 0, 0, 19, 9, 11, + 0, 11, 1, 11, 2, 17, 11, 12, 3, 10, 3, 41, 3, 11, 3, 2, 13, 1, + 0, 0, 0, 4, 11, 0, 56, 29, 56, 30, 2, 14, 1, 0, 0, 0, 2, 7, + 11, 2, 15, 1, 0, 2, 1, 3, 76, 189, 1, 14, 1, 17, 64, 12, 25, 14, + 2, 17, 64, 12, 27, 11, 25, 11, 27, 11, 3, 17, 10, 12, 19, 10, 0, 17, + 25, 10, 19, 56, 31, 12, 15, 14, 1, 17, 65, 12, 8, 14, 2, 17, 65, 12, + 9, 10, 8, 6, 0, 0, 0, 0, 0, 0, 0, 0, 36, 4, 31, 10, 9, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 36, 12, 4, 5, 33, 9, 12, 4, 11, 4, + 4, 36, 5, 40, 11, 0, 1, 7, 7, 39, 14, 19, 56, 2, 43, 3, 12, 20, + 10, 20, 16, 9, 20, 12, 23, 10, 20, 16, 10, 20, 12, 24, 10, 23, 56, 26, + 12, 21, 10, 24, 56, 26, 12, 22, 10, 19, 56, 32, 56, 30, 12, 16, 10, 20, + 16, 7, 16, 13, 12, 18, 10, 16, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 33, 4, 87, 11, 8, 53, 11, 9, 53, 24, 17, + 66, 52, 12, 29, 10, 18, 10, 19, 7, 11, 56, 33, 11, 29, 7, 11, 23, 12, + 5, 5, 153, 1, 11, 8, 10, 16, 52, 11, 21, 12, 12, 12, 10, 12, 6, 10, + 12, 6, 0, 0, 0, 0, 0, 0, 0, 0, 34, 4, 99, 5, 108, 11, 20, 1, + 11, 18, 1, 11, 0, 1, 6, 4, 0, 0, 0, 0, 0, 0, 0, 17, 58, 39, + 11, 6, 53, 11, 10, 53, 24, 11, 12, 53, 26, 52, 12, 26, 11, 9, 11, 16, + 52, 11, 22, 12, 13, 12, 11, 12, 7, 10, 13, 6, 0, 0, 0, 0, 0, 0, + 0, 0, 34, 4, 130, 1, 5, 139, 1, 11, 20, 1, 11, 18, 1, 11, 0, 1, + 6, 4, 0, 0, 0, 0, 0, 0, 0, 17, 58, 39, 11, 7, 53, 11, 11, 53, + 24, 11, 13, 53, 26, 52, 12, 28, 11, 26, 11, 28, 17, 68, 12, 5, 11, 5, + 12, 14, 10, 14, 6, 0, 0, 0, 0, 0, 0, 0, 0, 36, 4, 160, 1, 5, + 168, 1, 11, 20, 1, 11, 18, 1, 11, 0, 1, 7, 1, 39, 11, 23, 11, 1, + 56, 34, 11, 24, 11, 2, 56, 34, 11, 0, 17, 25, 11, 19, 17, 22, 11, 18, + 11, 14, 17, 70, 12, 17, 11, 20, 16, 7, 16, 8, 11, 15, 11, 17, 56, 35, + 2, 16, 1, 0, 1, 3, 82, 13, 14, 0, 56, 24, 43, 3, 12, 1, 10, 1, + 16, 9, 20, 56, 26, 11, 1, 16, 10, 20, 56, 26, 2, 17, 1, 0, 1, 3, + 82, 14, 14, 0, 56, 2, 43, 3, 12, 1, 10, 1, 16, 9, 20, 56, 6, 11, + 1, 16, 10, 20, 56, 6, 64, 42, 2, 0, 0, 0, 0, 0, 0, 0, 2, 18, + 3, 0, 3, 1, 3, 4, 83, 195, 1, 7, 12, 43, 4, 16, 14, 20, 32, 4, + 7, 5, 11, 11, 0, 1, 7, 6, 39, 14, 2, 17, 64, 12, 12, 14, 2, 17, + 65, 12, 6, 10, 1, 10, 12, 10, 6, 17, 6, 12, 10, 12, 7, 13, 2, 10, + 10, 17, 72, 12, 8, 14, 1, 56, 2, 43, 3, 12, 18, 10, 18, 12, 16, 10, + 16, 16, 9, 20, 56, 26, 77, 12, 19, 10, 16, 16, 10, 20, 56, 26, 77, 12, + 21, 11, 16, 16, 12, 20, 4, 66, 10, 19, 10, 19, 24, 10, 19, 24, 10, 21, + 24, 10, 21, 10, 21, 24, 11, 21, 24, 11, 19, 24, 22, 12, 3, 5, 70, 11, + 19, 11, 21, 24, 12, 3, 11, 3, 12, 14, 14, 1, 56, 2, 42, 1, 12, 9, + 10, 18, 16, 9, 20, 12, 23, 10, 18, 16, 10, 20, 12, 24, 11, 10, 53, 12, + 11, 10, 12, 10, 18, 16, 9, 20, 56, 6, 33, 4, 116, 11, 23, 11, 2, 56, + 34, 10, 18, 16, 3, 20, 11, 8, 56, 34, 10, 9, 16, 15, 20, 11, 11, 22, + 11, 9, 15, 15, 21, 11, 0, 11, 24, 11, 7, 56, 5, 12, 4, 5, 137, 1, + 11, 24, 11, 2, 56, 34, 10, 18, 16, 4, 20, 11, 8, 56, 34, 10, 9, 16, + 16, 20, 11, 11, 22, 11, 9, 15, 16, 21, 11, 0, 11, 23, 11, 7, 56, 5, + 12, 4, 11, 4, 12, 15, 11, 18, 12, 17, 10, 17, 16, 9, 20, 56, 26, 77, + 12, 20, 10, 17, 16, 10, 20, 56, 26, 77, 12, 22, 11, 17, 16, 12, 20, 4, + 174, 1, 10, 20, 10, 20, 24, 10, 20, 24, 10, 22, 24, 10, 22, 10, 22, 24, + 11, 22, 24, 11, 20, 24, 22, 12, 5, 5, 178, 1, 11, 20, 11, 22, 24, 12, + 5, 11, 5, 12, 13, 11, 14, 11, 13, 37, 4, 185, 1, 5, 187, 1, 7, 3, + 39, 14, 1, 56, 2, 11, 12, 11, 6, 18, 5, 56, 36, 11, 15, 2, 19, 1, + 0, 1, 3, 0, 6, 14, 0, 56, 2, 43, 3, 16, 11, 20, 2, 20, 1, 0, + 1, 4, 0, 5, 7, 12, 43, 4, 16, 0, 56, 0, 2, 21, 1, 4, 2, 1, + 3, 86, 36, 10, 3, 6, 0, 0, 0, 0, 0, 0, 0, 0, 36, 4, 5, 5, + 9, 11, 0, 1, 7, 7, 39, 11, 0, 17, 25, 12, 4, 10, 4, 10, 1, 56, + 31, 12, 5, 10, 2, 10, 1, 56, 31, 12, 6, 11, 4, 10, 1, 17, 22, 11, + 2, 10, 1, 17, 22, 14, 1, 56, 2, 43, 3, 16, 7, 16, 8, 11, 5, 11, + 6, 11, 3, 56, 37, 2, 22, 1, 4, 1, 1, 88, 139, 1, 14, 1, 56, 2, + 42, 1, 12, 14, 10, 14, 16, 15, 20, 12, 10, 10, 14, 16, 16, 20, 12, 11, + 10, 0, 10, 1, 56, 38, 53, 12, 17, 11, 1, 56, 39, 12, 18, 10, 17, 50, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 4, + 128, 1, 10, 14, 16, 17, 10, 0, 56, 40, 20, 12, 15, 10, 14, 16, 18, 10, + 0, 56, 40, 20, 12, 16, 10, 10, 11, 15, 23, 12, 12, 10, 11, 11, 16, 23, + 12, 13, 11, 12, 10, 17, 10, 18, 12, 6, 12, 4, 12, 2, 10, 6, 50, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 4, 55, + 5, 60, 11, 14, 1, 6, 4, 0, 0, 0, 0, 0, 0, 0, 17, 58, 39, 11, + 2, 77, 11, 4, 77, 24, 11, 6, 77, 26, 53, 12, 8, 11, 13, 11, 17, 11, + 18, 12, 7, 12, 5, 12, 3, 10, 7, 50, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 34, 4, 81, 5, 86, 11, 14, 1, 6, 4, + 0, 0, 0, 0, 0, 0, 0, 17, 58, 39, 11, 3, 77, 11, 5, 77, 24, 11, + 7, 77, 26, 53, 12, 9, 10, 8, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 36, 4, 112, 10, 14, 15, 1, 10, 0, 50, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 41, 12, + 19, 10, 19, 20, 11, 8, 22, 11, 19, 21, 10, 9, 50, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 4, 128, 1, 10, 14, 15, + 2, 10, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 56, 41, 12, 20, 10, 20, 20, 11, 9, 22, 11, 20, 21, 10, 14, 15, + 17, 10, 0, 11, 10, 56, 42, 11, 14, 15, 18, 11, 0, 11, 11, 56, 42, 2, + 4, 0, 1, 4, 1, 5, 3, 2, 3, 3, 4, 2, 4, 3, 3, 4, 2, 2, + 3, 0, 3, 1, 3, 5, 3, 6, 2, 1, 4, 1, 1, 0, 1, 1, 1, 2, + 1, 3, 0, 0, 0, + ] +}); + +#[rustfmt::skip] +pub static MODULE_COMPLEX_LIQUIDITY_POOL_WRAPPER: Lazy> = Lazy::new(|| { + vec![ + 161, 28, 235, 11, 6, 0, 0, 0, 12, 1, 0, 16, 2, 16, 40, 3, 56, 109, + 4, 165, 1, 8, 5, 173, 1, 243, 1, 7, 160, 3, 250, 3, 8, 154, 7, 64, + 6, 218, 7, 76, 16, 166, 8, 77, 10, 243, 8, 27, 12, 142, 9, 177, 3, 13, + 191, 12, 10, 0, 0, 1, 1, 1, 2, 1, 3, 1, 4, 1, 5, 1, 6, 0, + 7, 0, 8, 8, 0, 1, 9, 6, 0, 2, 12, 7, 1, 0, 1, 7, 13, 8, + 0, 1, 22, 8, 0, 1, 24, 0, 0, 2, 26, 2, 0, 3, 28, 7, 1, 0, + 0, 6, 30, 7, 0, 0, 10, 0, 1, 0, 0, 11, 2, 3, 0, 0, 14, 4, + 5, 0, 0, 15, 4, 1, 0, 0, 16, 6, 1, 0, 0, 17, 7, 1, 0, 1, + 25, 8, 9, 0, 7, 25, 10, 1, 0, 2, 27, 2, 12, 0, 3, 29, 1, 14, + 1, 0, 6, 31, 15, 16, 0, 4, 32, 17, 1, 0, 1, 33, 18, 3, 0, 1, + 34, 20, 21, 0, 7, 35, 22, 23, 0, 5, 36, 25, 26, 0, 4, 37, 29, 30, + 1, 8, 4, 38, 31, 9, 1, 8, 7, 16, 32, 9, 0, 4, 39, 33, 1, 0, + 7, 40, 35, 36, 1, 8, 9, 13, 16, 28, 17, 28, 20, 34, 6, 6, 12, 6, + 8, 1, 6, 8, 1, 3, 3, 1, 0, 2, 6, 12, 10, 2, 1, 8, 1, 2, + 6, 12, 1, 3, 11, 2, 1, 8, 3, 8, 1, 8, 1, 4, 6, 12, 6, 12, + 3, 1, 3, 11, 2, 1, 8, 3, 3, 3, 2, 6, 8, 1, 3, 1, 8, 5, + 4, 6, 12, 8, 5, 8, 5, 1, 2, 8, 6, 6, 8, 6, 1, 8, 6, 1, + 4, 1, 11, 7, 1, 9, 0, 1, 10, 2, 1, 8, 8, 7, 6, 8, 6, 11, + 7, 1, 4, 8, 8, 8, 8, 2, 8, 8, 8, 8, 1, 6, 8, 6, 2, 8, + 1, 8, 1, 1, 6, 8, 1, 1, 11, 2, 1, 8, 4, 4, 6, 12, 11, 2, + 1, 8, 4, 11, 2, 1, 8, 4, 1, 1, 11, 2, 1, 8, 3, 5, 11, 2, + 1, 8, 3, 11, 2, 1, 8, 4, 8, 1, 11, 2, 1, 8, 4, 8, 1, 1, + 6, 12, 1, 5, 8, 11, 2, 1, 8, 4, 6, 8, 1, 8, 5, 6, 8, 0, + 6, 8, 1, 11, 2, 1, 8, 4, 8, 5, 8, 5, 1, 8, 4, 2, 5, 11, + 2, 1, 9, 0, 1, 3, 3, 6, 12, 11, 2, 1, 9, 0, 3, 3, 6, 12, + 11, 2, 1, 8, 3, 8, 5, 2, 5, 8, 5, 1, 8, 3, 1, 11, 2, 1, + 9, 0, 2, 3, 3, 22, 108, 105, 113, 117, 105, 100, 105, 116, 121, 95, 112, 111, + 111, 108, 95, 119, 114, 97, 112, 112, 101, 114, 14, 102, 117, 110, 103, 105, 98, 108, + 101, 95, 97, 115, 115, 101, 116, 6, 111, 98, 106, 101, 99, 116, 6, 111, 112, 116, + 105, 111, 110, 22, 112, 114, 105, 109, 97, 114, 121, 95, 102, 117, 110, 103, 105, 98, + 108, 101, 95, 115, 116, 111, 114, 101, 6, 115, 105, 103, 110, 101, 114, 6, 115, 116, + 114, 105, 110, 103, 14, 108, 105, 113, 117, 105, 100, 105, 116, 121, 95, 112, 111, 111, + 108, 9, 65, 100, 100, 114, 101, 115, 115, 101, 115, 7, 77, 105, 110, 116, 82, 101, + 102, 13, 97, 100, 100, 95, 108, 105, 113, 117, 105, 100, 105, 116, 121, 21, 99, 114, + 101, 97, 116, 101, 95, 102, 117, 110, 103, 105, 98, 108, 101, 95, 97, 115, 115, 101, + 116, 6, 79, 98, 106, 101, 99, 116, 13, 76, 105, 113, 117, 105, 100, 105, 116, 121, + 80, 111, 111, 108, 11, 99, 114, 101, 97, 116, 101, 95, 112, 111, 111, 108, 22, 105, + 110, 105, 116, 105, 97, 108, 105, 122, 101, 95, 108, 105, 113, 117, 105, 100, 95, 112, + 97, 105, 114, 4, 115, 119, 97, 112, 15, 118, 101, 114, 105, 102, 121, 95, 114, 101, + 115, 101, 114, 118, 101, 115, 4, 112, 111, 111, 108, 12, 116, 111, 107, 101, 110, 95, + 49, 95, 109, 105, 110, 116, 12, 116, 111, 107, 101, 110, 95, 50, 95, 109, 105, 110, + 116, 7, 116, 111, 107, 101, 110, 95, 49, 8, 77, 101, 116, 97, 100, 97, 116, 97, + 7, 116, 111, 107, 101, 110, 95, 50, 13, 70, 117, 110, 103, 105, 98, 108, 101, 65, + 115, 115, 101, 116, 4, 109, 105, 110, 116, 14, 67, 111, 110, 115, 116, 114, 117, 99, + 116, 111, 114, 82, 101, 102, 19, 99, 114, 101, 97, 116, 101, 95, 110, 97, 109, 101, + 100, 95, 111, 98, 106, 101, 99, 116, 6, 79, 112, 116, 105, 111, 110, 4, 110, 111, + 110, 101, 6, 83, 116, 114, 105, 110, 103, 4, 117, 116, 102, 56, 43, 99, 114, 101, + 97, 116, 101, 95, 112, 114, 105, 109, 97, 114, 121, 95, 115, 116, 111, 114, 101, 95, + 101, 110, 97, 98, 108, 101, 100, 95, 102, 117, 110, 103, 105, 98, 108, 101, 95, 97, + 115, 115, 101, 116, 17, 103, 101, 110, 101, 114, 97, 116, 101, 95, 109, 105, 110, 116, + 95, 114, 101, 102, 17, 109, 105, 110, 116, 95, 114, 101, 102, 95, 109, 101, 116, 97, + 100, 97, 116, 97, 6, 99, 114, 101, 97, 116, 101, 10, 97, 100, 100, 114, 101, 115, + 115, 95, 111, 102, 7, 98, 97, 108, 97, 110, 99, 101, 8, 119, 105, 116, 104, 100, + 114, 97, 119, 7, 100, 101, 112, 111, 115, 105, 116, 13, 112, 111, 111, 108, 95, 114, + 101, 115, 101, 114, 118, 101, 115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 171, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, + 8, 1, 0, 0, 0, 0, 0, 0, 0, 3, 8, 2, 0, 0, 0, 0, 0, 0, + 0, 10, 2, 1, 0, 10, 2, 6, 5, 116, 101, 115, 116, 49, 10, 2, 6, 5, + 116, 101, 115, 116, 50, 5, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 10, 77, 111, 118, 101, 83, 116, 100, 108, 105, 98, 0, + 0, 171, 205, 18, 97, 112, 116, 111, 115, 58, 58, 109, 101, 116, 97, 100, 97, 116, + 97, 95, 118, 49, 57, 2, 1, 0, 0, 0, 0, 0, 0, 0, 20, 69, 65, 68, + 68, 82, 69, 83, 83, 69, 83, 95, 78, 79, 84, 95, 70, 79, 85, 78, 68, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 14, 69, 78, 79, 84, 95, 80, 85, 66, 76, + 73, 83, 72, 69, 82, 0, 0, 0, 0, 2, 5, 18, 11, 2, 1, 8, 3, 19, + 8, 1, 20, 8, 1, 21, 11, 2, 1, 8, 4, 23, 11, 2, 1, 8, 4, 0, + 1, 0, 0, 1, 10, 11, 0, 11, 1, 11, 3, 17, 6, 11, 2, 11, 4, 17, + 6, 11, 5, 17, 7, 2, 1, 1, 0, 0, 11, 21, 11, 0, 10, 1, 17, 8, + 12, 2, 14, 2, 12, 3, 10, 3, 56, 0, 10, 1, 17, 10, 11, 1, 17, 10, + 49, 8, 7, 2, 17, 10, 7, 2, 17, 10, 17, 11, 11, 3, 17, 12, 2, 2, + 1, 0, 0, 19, 18, 10, 0, 7, 3, 17, 1, 12, 2, 10, 0, 7, 4, 17, + 1, 12, 3, 11, 0, 14, 2, 17, 13, 14, 3, 17, 13, 11, 1, 17, 14, 11, + 2, 11, 3, 2, 3, 1, 4, 0, 24, 45, 10, 0, 17, 15, 7, 5, 33, 4, + 6, 5, 10, 11, 0, 1, 7, 1, 39, 10, 0, 10, 1, 17, 2, 12, 6, 12, + 4, 12, 2, 10, 0, 14, 4, 14, 6, 6, 0, 225, 245, 5, 0, 0, 0, 0, + 6, 0, 194, 235, 11, 0, 0, 0, 0, 10, 1, 17, 0, 11, 1, 32, 4, 30, + 10, 2, 6, 0, 225, 245, 5, 0, 0, 0, 0, 6, 0, 194, 235, 11, 0, 0, + 0, 0, 17, 5, 14, 4, 17, 13, 12, 3, 14, 6, 17, 13, 12, 5, 11, 0, + 11, 2, 11, 4, 11, 6, 11, 3, 11, 5, 18, 0, 45, 0, 2, 4, 1, 4, + 1, 0, 27, 79, 10, 1, 17, 15, 7, 5, 33, 4, 6, 5, 12, 11, 0, 1, + 11, 1, 1, 7, 1, 39, 7, 5, 41, 0, 4, 16, 5, 22, 11, 0, 1, 11, + 1, 1, 7, 0, 39, 7, 5, 43, 0, 12, 7, 11, 3, 4, 35, 10, 7, 16, + 0, 20, 10, 7, 16, 1, 12, 5, 12, 4, 5, 42, 10, 7, 16, 2, 20, 10, + 7, 16, 3, 12, 5, 12, 4, 11, 4, 11, 5, 12, 8, 12, 9, 10, 0, 17, + 15, 10, 9, 56, 1, 10, 2, 38, 4, 61, 11, 8, 1, 10, 0, 11, 9, 11, + 2, 56, 2, 12, 6, 5, 65, 11, 8, 11, 2, 17, 6, 12, 6, 11, 6, 12, + 11, 11, 1, 11, 7, 16, 4, 20, 11, 11, 17, 18, 12, 10, 11, 0, 17, 15, + 11, 10, 17, 19, 2, 5, 0, 0, 0, 30, 17, 11, 0, 56, 3, 12, 3, 11, + 1, 33, 4, 7, 5, 9, 6, 0, 0, 0, 0, 0, 0, 0, 0, 39, 11, 3, + 11, 2, 33, 4, 14, 5, 16, 6, 0, 0, 0, 0, 0, 0, 0, 0, 39, 2, + 0, 3, 0, 1, 0, 4, 0, 2, 0, 0, 0, ] }); @@ -171,6 +714,8 @@ pub static MODULE_COMPLEX_VECTOR_PICTURE: Lazy> = Lazy::new(|| { #[rustfmt::skip] pub static MODULES_COMPLEX: Lazy>> = Lazy::new(|| { vec![ + MODULE_COMPLEX_LIQUIDITY_POOL.to_vec(), + MODULE_COMPLEX_LIQUIDITY_POOL_WRAPPER.to_vec(), MODULE_COMPLEX_SMART_TABLE_PICTURE.to_vec(), MODULE_COMPLEX_VECTOR_PICTURE.to_vec(), ]}); diff --git a/testsuite/module-publish/src/packages/complex/Move.toml b/testsuite/module-publish/src/packages/complex/Move.toml index 7a8c763886529..470371e2ae103 100644 --- a/testsuite/module-publish/src/packages/complex/Move.toml +++ b/testsuite/module-publish/src/packages/complex/Move.toml @@ -5,3 +5,5 @@ version = '1.0.0' [dependencies] AptosFramework = { local = "../../../../../aptos-move/framework/aptos-framework" } +[addresses] +publisher_address = "0xABCD" diff --git a/testsuite/module-publish/src/packages/complex/sources/liquid_pool/liquidity_pool.move b/testsuite/module-publish/src/packages/complex/sources/liquid_pool/liquidity_pool.move new file mode 100644 index 0000000000000..44e7aa15a377f --- /dev/null +++ b/testsuite/module-publish/src/packages/complex/sources/liquid_pool/liquidity_pool.move @@ -0,0 +1,612 @@ +/// Copied from aptos-move/move-examples/swap/sources/liquidity_pool.move +/// +/// For volatile pairs, the price and reserves can be computed using the constant product formula k = x * y. +/// For stable pairs, the price is computed using k = x^3 * y + x * y^3. +module publisher_address::liquidity_pool { + use aptos_framework::event; + use aptos_framework::fungible_asset::{ + Self, FungibleAsset, FungibleStore, Metadata, + BurnRef, MintRef, TransferRef, + }; + use aptos_framework::object::{Self, ConstructorRef, Object}; + use aptos_framework::primary_fungible_store; + // use aptos_std::comparator; + use aptos_std::math128; + use aptos_std::math64; + use aptos_std::smart_table::{Self, SmartTable}; + use aptos_std::smart_vector::{Self, SmartVector}; + + use std::bcs; + use std::option; + use std::signer; + use std::string::{Self, String}; + use std::vector; + + friend publisher_address::liquidity_pool_wrapper; + + const FEE_SCALE: u64 = 10000; + const LP_TOKEN_DECIMALS: u8 = 8; + const MINIMUM_LIQUIDITY: u64 = 1000; + const MAX_SWAP_FEES_BPS: u64 = 25; // 0.25% + + /// Amount of tokens provided must be greater than zero. + const EZERO_AMOUNT: u64 = 1; + /// The amount of liquidity provided is so small that corresponding LP token amount is rounded to zero. + const EINSUFFICIENT_LIQUIDITY_MINTED: u64 = 2; + /// Amount of LP tokens redeemed is too small, so amounts of tokens received back are rounded to zero. + const EINSUFFICIENT_LIQUIDITY_REDEEMED: u64 = 3; + /// The specified amount of output tokens is incorrect and does not maintain the pool's invariant. + const EINCORRECT_SWAP_AMOUNT: u64 = 4; + /// The caller is not the owner of the LP token store. + const ENOT_STORE_OWNER: u64 = 5; + /// Claler is not authorized to perform the operation. + const ENOT_AUTHORIZED: u64 = 6; + /// All swaps are currently paused. + const ESWAPS_ARE_PAUSED: u64 = 7; + /// Swap leaves pool in a worse state than before. + const EK_BEFORE_SWAP_GREATER_THAN_EK_AFTER_SWAP: u64 = 8; + + struct LPTokenRefs has store { + burn_ref: BurnRef, + mint_ref: MintRef, + transfer_ref: TransferRef, + } + + /// Stored in the protocol's account for configuring liquidity pools. + struct LiquidityPoolConfigs has key { + all_pools: SmartVector>, + is_paused: bool, + stable_fee_bps: u64, + volatile_fee_bps: u64, + } + + #[resource_group_member(group = aptos_framework::object::ObjectGroup)] + struct LiquidityPool has key { + token_store_1: Object, + token_store_2: Object, + fees_store_1: Object, + fees_store_2: Object, + lp_token_refs: LPTokenRefs, + swap_fee_bps: u64, + is_stable: bool, + } + + #[resource_group_member(group = aptos_framework::object::ObjectGroup)] + struct FeesAccounting has key { + total_fees_1: u128, + total_fees_2: u128, + total_fees_at_last_claim_1: SmartTable, + total_fees_at_last_claim_2: SmartTable, + claimable_1: SmartTable, + claimable_2: SmartTable, + } + + #[event] + /// Event emitted when a pool is created. + struct CreatePool has drop, store { + pool: Object, + token_1: Object, + token_2: Object, + is_stable: bool, + } + + #[event] + /// Event emitted when a swap happens. + struct Swap has drop, store { + pool: address, + from_token: Object, + amount_in: u64, + } + + fun init_module(publisher: &signer) { + move_to(publisher, LiquidityPoolConfigs { + all_pools: smart_vector::new(), + is_paused: false, + stable_fee_bps: 10, // 0.1% + volatile_fee_bps: 20, // 0.2% + }); + } + + #[view] + public fun total_number_of_pools(): u64 acquires LiquidityPoolConfigs { + smart_vector::length(&safe_liquidity_pool_configs().all_pools) + } + + #[view] + public fun all_pools(): vector> acquires LiquidityPoolConfigs { + let all_pools = &safe_liquidity_pool_configs().all_pools; + let results = vector[]; + let len = smart_vector::length(all_pools); + let i = 0; + while (i < len) { + vector::push_back(&mut results, *smart_vector::borrow(all_pools, i)); + i = i + 1; + }; + results + } + + #[view] + public fun liquidity_pool( + token_1: Object, + token_2: Object, + is_stable: bool, + ): Object { + object::address_to_object(liquidity_pool_address(token_1, token_2, is_stable)) + } + + #[view] + public fun liquidity_pool_address_safe( + token_1: Object, + token_2: Object, + is_stable: bool, + ): (bool, address) { + let pool_address = liquidity_pool_address(token_1, token_2, is_stable); + (exists(pool_address), pool_address) + } + + #[view] + public fun liquidity_pool_address( + token_1: Object, + token_2: Object, + is_stable: bool, + ): address { + // if (!is_sorted(token_1, token_2)) { + // return liquidity_pool_address(token_2, token_1, is_stable) + // }; + object::create_object_address(&@publisher_address, get_pool_seeds(token_1, token_2, is_stable)) + } + + #[view] + public fun lp_token_supply(pool: Object): u128 { + option::destroy_some(fungible_asset::supply(pool)) + } + + #[view] + public fun pool_reserves(pool: Object): (u64, u64) acquires LiquidityPool { + let pool_data = liquidity_pool_data(&pool); + ( + fungible_asset::balance(pool_data.token_store_1), + fungible_asset::balance(pool_data.token_store_2), + ) + } + + #[view] + public fun supported_inner_assets(pool: Object): vector> acquires LiquidityPool { + let pool_data = liquidity_pool_data(&pool); + vector[ + fungible_asset::store_metadata(pool_data.token_store_1), + fungible_asset::store_metadata(pool_data.token_store_2), + ] + } + + // #[view] + // public fun is_sorted(token_1: Object, token_2: Object): bool { + // let token_1_addr = object::object_address(&token_1); + // let token_2_addr = object::object_address(&token_2); + // comparator::is_smaller_than(&comparator::compare(&token_1_addr, &token_2_addr)) + // } + + #[view] + public fun is_stable(pool: Object): bool acquires LiquidityPool { + liquidity_pool_data(&pool).is_stable + } + + #[view] + public fun swap_fee_bps(pool: Object): u64 acquires LiquidityPool { + liquidity_pool_data(&pool).swap_fee_bps + } + + #[view] + public fun min_liquidity(): u64 { + MINIMUM_LIQUIDITY + } + + #[view] + public fun claimable_fees(lp: address, pool: Object): (u128, u128) acquires FeesAccounting { + let fees_accounting = safe_fees_accounting(&pool); + ( + *smart_table::borrow_with_default(&fees_accounting.claimable_1, lp, &0), + *smart_table::borrow_with_default(&fees_accounting.claimable_2, lp, &0), + ) + } + + /// Creates a new liquidity pool. + public fun create( + publisher: &signer, + token_1: Object, + token_2: Object, + is_stable: bool, + ): Object acquires LiquidityPoolConfigs { + // if (!is_sorted(token_1, token_2)) { + // return create(publisher, token_2, token_1, is_stable) + // }; + let configs = unchecked_mut_liquidity_pool_configs(); + + // The liquidity pool will serve 3 separate roles: + // 1. Represent the liquidity pool that LPs and users interact with to add/remove liquidity and swap tokens. + // 2. Represent the metadata of the LP token. + // 3. Store the min liquidity that will be locked into the pool when initial liquidity is added. + let pool_constructor_ref = create_lp_token(publisher, token_1, token_2, is_stable); + let pool_signer = &object::generate_signer(pool_constructor_ref); + let lp_token = object::object_from_constructor_ref(pool_constructor_ref); + fungible_asset::create_store(pool_constructor_ref, lp_token); + move_to(pool_signer, LiquidityPool { + token_store_1: create_token_store(pool_signer, token_1), + token_store_2: create_token_store(pool_signer, token_2), + fees_store_1: create_token_store(pool_signer, token_1), + fees_store_2: create_token_store(pool_signer, token_2), + lp_token_refs: create_lp_token_refs(pool_constructor_ref), + swap_fee_bps: if (is_stable) { configs.stable_fee_bps } else { configs.volatile_fee_bps }, + is_stable, + }); + move_to(pool_signer, FeesAccounting { + total_fees_1: 0, + total_fees_2: 0, + total_fees_at_last_claim_1: smart_table::new(), + total_fees_at_last_claim_2: smart_table::new(), + claimable_1: smart_table::new(), + claimable_2: smart_table::new(), + }); + let pool = object::convert(lp_token); + smart_vector::push_back(&mut configs.all_pools, pool); + + event::emit(CreatePool { pool, token_1, token_2, is_stable }); + pool + } + + /////////////////////////////////////////////////// USERS ///////////////////////////////////////////////////////// + + #[view] + /// Return the amount of tokens received for a swap with the given amount in and the liquidity pool. + public fun get_amount_out( + pool: Object, + from: Object, + amount_in: u64, + ): (u64, u64) acquires LiquidityPool { + let pool_data = liquidity_pool_data(&pool); + let reserve_1 = (fungible_asset::balance(pool_data.token_store_1) as u256); + let reserve_2 = (fungible_asset::balance(pool_data.token_store_2) as u256); + let (reserve_in, reserve_out) = if (from == fungible_asset::store_metadata(pool_data.token_store_1)) { + (reserve_1, reserve_2) + } else { + (reserve_2, reserve_1) + }; + let fees_amount = math64::mul_div(amount_in, pool_data.swap_fee_bps, FEE_SCALE); + let amount_in = ((amount_in - fees_amount) as u256); + let amount_out = if (pool_data.is_stable) { + let k = calculate_constant_k(pool_data); + reserve_out - get_y(amount_in + reserve_in, k, reserve_out) + } else { + amount_in * reserve_out / (reserve_in + amount_in) + }; + ((amount_out as u64), fees_amount) + } + + /// Swaps `from` for the other token in the pool. + /// This is friend-only as the returned fungible assets might be of an internal wrapper type. If this is not the + /// case, this function can be made public. + public(friend) fun swap( + publisher: &signer, + pool: Object, + from: FungibleAsset, + ): FungibleAsset acquires FeesAccounting, LiquidityPool, LiquidityPoolConfigs { + assert!(!safe_liquidity_pool_configs().is_paused, ESWAPS_ARE_PAUSED); + // Calculate the amount of tokens to return to the user and the amount of fees to extract. + let from_token = fungible_asset::metadata_from_asset(&from); + let amount_in = fungible_asset::amount(&from); + let (amount_out, fees_amount) = get_amount_out(pool, from_token, amount_in); + let fees = fungible_asset::extract(&mut from, fees_amount); + + // Deposits and withdraws. + let pool_data = liquidity_pool_data(&pool); + let k_before = calculate_constant_k(pool_data); + let fees_accounting = unchecked_mut_fees_accounting(&pool); + let store_1 = pool_data.token_store_1; + let store_2 = pool_data.token_store_2; + let fees_amount = (fees_amount as u128); + let out = if (from_token == fungible_asset::store_metadata(pool_data.token_store_1)) { + // User's swapping token 1 for token 2. + fungible_asset::deposit(store_1, from); + fungible_asset::deposit(pool_data.fees_store_1, fees); + fees_accounting.total_fees_1 = fees_accounting.total_fees_1 + fees_amount; + fungible_asset::withdraw(publisher, store_2, amount_out) + } else { + // User's swapping token 2 for token 1. + fungible_asset::deposit(store_2, from); + fungible_asset::deposit(pool_data.fees_store_2, fees); + fees_accounting.total_fees_2 = fees_accounting.total_fees_2 + fees_amount; + fungible_asset::withdraw(publisher, store_1, amount_out) + }; + + let k_after = calculate_constant_k(pool_data); + assert!(k_before <= k_after, EK_BEFORE_SWAP_GREATER_THAN_EK_AFTER_SWAP); + + event::emit(Swap { pool: object::object_address(&pool), from_token, amount_in }, ); + out + } + + //////////////////////////////////////// Liquidity Providers (LPs) /////////////////////////////////////////////// + + /// Mint LP tokens for the given liquidity. Note that the LP would receive a smaller amount of LP tokens if the + /// amounts of liquidity provided are not optimal (do not conform with the constant formula of the pool). Users + /// should compute the optimal amounts before calling this function. + public fun mint( + lp: &signer, + fungible_asset_1: FungibleAsset, + fungible_asset_2: FungibleAsset, + is_stable: bool, + ) acquires FeesAccounting, LiquidityPool { + let token_1 = fungible_asset::metadata_from_asset(&fungible_asset_1); + let token_2 = fungible_asset::metadata_from_asset(&fungible_asset_2); + // if (!is_sorted(token_1, token_2)) { + // return mint(lp, fungible_asset_2, fungible_asset_1, is_stable) + // }; + // The LP store needs to exist before we can mint LP tokens. + let pool = liquidity_pool(token_1, token_2, is_stable); + let lp_store = ensure_lp_token_store(signer::address_of(lp), pool); + let amount_1 = fungible_asset::amount(&fungible_asset_1); + let amount_2 = fungible_asset::amount(&fungible_asset_2); + assert!(amount_1 > 0 && amount_2 > 0, EZERO_AMOUNT); + let pool_data = liquidity_pool_data(&pool); + let store_1 = pool_data.token_store_1; + let store_2 = pool_data.token_store_2; + + // Before depositing the added liquidity, compute the amount of LP tokens the LP will receive. + let reserve_1 = fungible_asset::balance(store_1); + let reserve_2 = fungible_asset::balance(store_2); + let lp_token_supply = option::destroy_some(fungible_asset::supply(pool)); + let mint_ref = &pool_data.lp_token_refs.mint_ref; + let liquidity_token_amount = if (lp_token_supply == 0) { + let total_liquidity = (math128::sqrt((amount_1 as u128) * (amount_2 as u128)) as u64); + // Permanently lock the first MINIMUM_LIQUIDITY tokens. + fungible_asset::mint_to(mint_ref, pool, MINIMUM_LIQUIDITY); + total_liquidity - MINIMUM_LIQUIDITY + } else { + // Only the smaller amount between the token 1 or token 2 is considered. Users should make sure to either + // use the router module or calculate the optimal amounts to provide before calling this function. + let token_1_liquidity = math64::mul_div(amount_1, (lp_token_supply as u64), reserve_1); + let token_2_liquidity = math64::mul_div(amount_2, (lp_token_supply as u64), reserve_2); + math64::min(token_1_liquidity, token_2_liquidity) + }; + assert!(liquidity_token_amount > 0, EINSUFFICIENT_LIQUIDITY_MINTED); + + // Deposit the received liquidity into the pool. + fungible_asset::deposit(store_1, fungible_asset_1); + fungible_asset::deposit(store_2, fungible_asset_2); + + // We need to update the amount of rewards claimable by this LP token store if they already have a previous + // balance. This ensures that their update balance would not lead to earning a larger portion of the fees + // retroactively. + update_claimable_fees(signer::address_of(lp), pool); + + // Mint the corresponding amount of LP tokens to the LP. + let lp_tokens = fungible_asset::mint(mint_ref, liquidity_token_amount); + fungible_asset::deposit_with_ref(&pool_data.lp_token_refs.transfer_ref, lp_store, lp_tokens); + } + + /// Transfer a given amount of LP tokens from the sender to the receiver. This must be called for all transfers as + /// fungible_asset::transfer or primary_fungible_store::transfer would not work for LP tokens. + public entry fun transfer( + from: &signer, + lp_token: Object, + to: address, + amount: u64, + ) acquires FeesAccounting, LiquidityPool { + assert!(amount > 0, EZERO_AMOUNT); + let from_address = signer::address_of(from); + let from_store = ensure_lp_token_store(from_address, lp_token); + let to_store = ensure_lp_token_store(to, lp_token); + + // Update the claimable amounts for both the sender and receiver before transferring. + update_claimable_fees(from_address, lp_token); + update_claimable_fees(to, lp_token); + + let transfer_ref = &liquidity_pool_data(&lp_token).lp_token_refs.transfer_ref; + fungible_asset::transfer_with_ref(transfer_ref, from_store, to_store, amount); + } + + /// Calculate and update the latest amount of fees claimable by the given LP. + public entry fun update_claimable_fees(lp: address, pool: Object) acquires FeesAccounting { + let fees_accounting = unchecked_mut_fees_accounting(&pool); + let current_total_fees_1 = fees_accounting.total_fees_1; + let current_total_fees_2 = fees_accounting.total_fees_2; + let lp_balance = (primary_fungible_store::balance(lp, pool) as u128); + let lp_token_total_supply = lp_token_supply(pool); + // Calculate and update the amount of fees this LP token store is entitled to, taking into account the last + // time they claimed. + if (lp_balance > 0) { + let last_total_fees_1 = *smart_table::borrow(&fees_accounting.total_fees_at_last_claim_1, lp); + let last_total_fees_2 = *smart_table::borrow(&fees_accounting.total_fees_at_last_claim_2, lp); + let delta_1 = current_total_fees_1 - last_total_fees_1; + let delta_2 = current_total_fees_2 - last_total_fees_2; + let claimable_1 = math128::mul_div(delta_1, lp_balance, lp_token_total_supply); + let claimable_2 = math128::mul_div(delta_2, lp_balance, lp_token_total_supply); + if (claimable_1 > 0) { + let old_claimable_1 = smart_table::borrow_mut_with_default(&mut fees_accounting.claimable_1, lp, 0); + *old_claimable_1 = *old_claimable_1 + claimable_1; + }; + if (claimable_2 > 0) { + let old_claimable_2 = smart_table::borrow_mut_with_default(&mut fees_accounting.claimable_2, lp, 0); + *old_claimable_2 = *old_claimable_2 + claimable_2; + }; + }; + + smart_table::upsert(&mut fees_accounting.total_fees_at_last_claim_1, lp, current_total_fees_1); + smart_table::upsert(&mut fees_accounting.total_fees_at_last_claim_2, lp, current_total_fees_2); + } + + /// Claim the fees that the given LP is entitled to. + /// This is friend-only as the returned fungible assets might be of an internal wrapper type. If this is not the + /// case, this function can be made public. + public(friend) fun claim_fees( + publisher: &signer, + lp: &signer, + pool: Object, + ): (FungibleAsset, FungibleAsset) acquires FeesAccounting, LiquidityPool { + let lp_address = signer::address_of(lp); + update_claimable_fees(lp_address, pool); + + let pool_data = liquidity_pool_data(&pool); + let fees_accounting = unchecked_mut_fees_accounting(&pool); + let claimable_1 = if (smart_table::contains(&fees_accounting.claimable_1, lp_address)) { + smart_table::remove(&mut fees_accounting.claimable_1, lp_address) + } else { + 0 + }; + let claimable_2 = if (smart_table::contains(&fees_accounting.claimable_2, lp_address)) { + smart_table::remove(&mut fees_accounting.claimable_2, lp_address) + } else { + 0 + }; + let fees_1 = if (claimable_1 > 0) { + fungible_asset::withdraw(publisher, pool_data.fees_store_1, (claimable_1 as u64)) + } else { + fungible_asset::zero(fungible_asset::store_metadata(pool_data.fees_store_1)) + }; + let fees_2 = if (claimable_2 > 0) { + fungible_asset::withdraw(publisher, pool_data.fees_store_2, (claimable_2 as u64)) + } else { + fungible_asset::zero(fungible_asset::store_metadata(pool_data.fees_store_2)) + }; + (fees_1, fees_2) + } + + /////////////////////////////////////////////////// OPERATIONS ///////////////////////////////////////////////////// + + + inline fun create_lp_token( + publisher: &signer, + token_1: Object, + token_2: Object, + is_stable: bool, + ): &ConstructorRef { + let token_name = lp_token_name(token_1, token_2); + let seeds = get_pool_seeds(token_1, token_2, is_stable); + let lp_token_constructor_ref = &object::create_named_object(publisher, seeds); + // We don't enable automatic primary store creation because we need LPs to call into this module for transfers + // so the fees accounting can be updated correctly. + primary_fungible_store::create_primary_store_enabled_fungible_asset( + lp_token_constructor_ref, + option::none(), + token_name, + string::utf8(b"LP"), + LP_TOKEN_DECIMALS, + string::utf8(b""), + string::utf8(b"") + ); + lp_token_constructor_ref + } + + fun create_lp_token_refs(constructor_ref: &ConstructorRef): LPTokenRefs { + LPTokenRefs { + burn_ref: fungible_asset::generate_burn_ref(constructor_ref), + mint_ref: fungible_asset::generate_mint_ref(constructor_ref), + transfer_ref: fungible_asset::generate_transfer_ref(constructor_ref), + } + } + + fun ensure_lp_token_store(lp: address, pool: Object): Object acquires LiquidityPool { + primary_fungible_store::ensure_primary_store_exists(lp, pool); + let store = primary_fungible_store::primary_store(lp, pool); + if (!fungible_asset::is_frozen(store)) { + // LPs must call transfer here to transfer the LP tokens so claimable fees can be updated correctly. + let transfer_ref = &liquidity_pool_data(&pool).lp_token_refs.transfer_ref; + fungible_asset::set_frozen_flag(transfer_ref, store, true); + }; + store + } + + inline fun get_pool_seeds(token_1: Object, token_2: Object, is_stable: bool): vector { + let seeds = vector[]; + vector::append(&mut seeds, bcs::to_bytes(&object::object_address(&token_1))); + vector::append(&mut seeds, bcs::to_bytes(&object::object_address(&token_2))); + vector::append(&mut seeds, bcs::to_bytes(&is_stable)); + seeds + } + + inline fun create_token_store(pool_signer: &signer, token: Object): Object { + let constructor_ref = &object::create_object_from_object(pool_signer); + fungible_asset::create_store(constructor_ref, token) + } + + inline fun lp_token_name(token_1: Object, token_2: Object): String { + let token_symbol = string::utf8(b"LP-"); + string::append(&mut token_symbol, fungible_asset::symbol(token_1)); + string::append_utf8(&mut token_symbol, b"-"); + string::append(&mut token_symbol, fungible_asset::symbol(token_2)); + token_symbol + } + + inline fun calculate_constant_k(pool: &LiquidityPool): u256 { + let r1 = (fungible_asset::balance(pool.token_store_1) as u256); + let r2 = (fungible_asset::balance(pool.token_store_2) as u256); + if (pool.is_stable) { + // k = x^3 * y + y^3 * x. This is a modified constant for stable pairs. + r1 * r1 * r1 * r2 + r2 * r2 * r2 * r1 + } else { + // k = x * y. This is standard constant product for volatile asset pairs. + r1 * r2 + } + } + + inline fun safe_fees_accounting(pool: &Object): &FeesAccounting acquires FeesAccounting { + borrow_global(object::object_address(pool)) + } + + inline fun liquidity_pool_data(pool: &Object): &LiquidityPool acquires LiquidityPool { + borrow_global(object::object_address(pool)) + } + + inline fun safe_liquidity_pool_configs(): &LiquidityPoolConfigs acquires LiquidityPoolConfigs { + borrow_global(@publisher_address) + } + + inline fun unchecked_mut_liquidity_pool_data(pool: &Object): &mut LiquidityPool acquires LiquidityPool { + borrow_global_mut(object::object_address(pool)) + } + + inline fun unchecked_mut_fees_accounting(pool: &Object): &mut FeesAccounting acquires FeesAccounting { + borrow_global_mut(object::object_address(pool)) + } + + inline fun unchecked_mut_liquidity_pool_configs(): &mut LiquidityPoolConfigs acquires LiquidityPoolConfigs { + borrow_global_mut(@publisher_address) + } + + inline fun f(x0: u256, y: u256): u256 { + x0 * (y * y * y) + (x0 * x0 * x0) * y + } + + inline fun d(x0: u256, y: u256): u256 { + 3 * x0 * (y * y) + (x0 * x0 * x0) + } + + fun get_y(x0: u256, xy: u256, y: u256): u256 { + let i = 0; + while (i < 255) { + let y_prev = y; + let k = f(x0, y); + if (k < xy) { + let dy = (xy - k) / d(x0, y); + y = y + dy; + } else { + let dy = (k - xy) / d(x0, y); + y = y - dy; + }; + if (y > y_prev) { + if (y - y_prev <= 1) { + return y + } + } else { + if (y_prev - y <= 1) { + return y + } + }; + i = i + 1; + }; + y + } + + #[test_only] + friend swap::liquidity_pool_tests; +} diff --git a/testsuite/module-publish/src/packages/complex/sources/liquid_pool/liquidity_pool_wrapper.move b/testsuite/module-publish/src/packages/complex/sources/liquid_pool/liquidity_pool_wrapper.move new file mode 100644 index 0000000000000..a02fb54a5a593 --- /dev/null +++ b/testsuite/module-publish/src/packages/complex/sources/liquid_pool/liquidity_pool_wrapper.move @@ -0,0 +1,120 @@ +// benchmark is run without indexer, so we need to do bookeeping onchain. + +module publisher_address::liquidity_pool_wrapper { + use aptos_framework::fungible_asset::{Self, Metadata, MintRef}; + use aptos_framework::object::{Self, Object}; + use aptos_framework::primary_fungible_store; + use publisher_address::liquidity_pool::{Self, LiquidityPool}; + use std::option; + use std::string; + use std::signer; + + const EADDRESSES_NOT_FOUND: u64 = 1; + const ENOT_PUBLISHER: u64 = 2; + + struct Addresses has key { + pool: Object, + token_1_mint: MintRef, + token_2_mint: MintRef, + token_1: Object, + token_2: Object, + } + + public entry fun initialize_liquid_pair(publisher: &signer, is_stable: bool) { + assert!(signer::address_of(publisher) == @publisher_address, ENOT_PUBLISHER); + + let (pool, token_1_mint, token_2_mint) = create_pool(publisher, is_stable); + + // Add liquidity to the pool + add_liquidity(publisher, &token_1_mint, &token_2_mint, 100000000, 200000000, is_stable); + if (!is_stable) { + verify_reserves(pool, 100000000, 200000000); + }; + let token_1 = fungible_asset::mint_ref_metadata(&token_1_mint); + let token_2 = fungible_asset::mint_ref_metadata(&token_2_mint); + move_to( + publisher, + Addresses { + pool: pool, + token_1_mint, + token_2_mint, + token_1, + token_2, + } + ) + } + + public entry fun swap( + user: &signer, + publisher: &signer, + amount_in: u64, + from_1: bool, + ) acquires Addresses { + assert!(signer::address_of(publisher) == @publisher_address, ENOT_PUBLISHER); + assert!(exists(@publisher_address), EADDRESSES_NOT_FOUND); + let addresses = borrow_global(@publisher_address); + + let (from_token, from_mint) = if (from_1) { + (addresses.token_1, &addresses.token_1_mint) + } else { + (addresses.token_2, &addresses.token_2_mint) + }; + + let tokens = if (primary_fungible_store::balance(signer::address_of(user), from_token) >= amount_in) { + primary_fungible_store::withdraw(user, from_token, amount_in) + } else { + fungible_asset::mint(from_mint, amount_in) + }; + let out = liquidity_pool::swap(publisher, addresses.pool, tokens); + primary_fungible_store::deposit(signer::address_of(user), out); + } + + fun verify_reserves(pool: Object, expected_1: u64, expected_2: u64) { + let (reserves_1, reserves_2) = liquidity_pool::pool_reserves(pool); + assert!(reserves_1 == expected_1, 0); + assert!(reserves_2 == expected_2, 0); + } + + public fun add_liquidity( + lp: &signer, + mint_1_ref: &MintRef, + mint_2_ref: &MintRef, + amount_1: u64, + amount_2: u64, + is_stable: bool, + ) { + liquidity_pool::mint( + lp, + fungible_asset::mint(mint_1_ref, amount_1), + fungible_asset::mint(mint_2_ref, amount_2), + is_stable, + ); + } + + public fun create_pool(publisher: &signer, is_stable: bool): (Object, MintRef, MintRef) { + let mint_1 = create_fungible_asset(publisher, b"test1"); + let mint_2 = create_fungible_asset(publisher, b"test2"); + let pool = liquidity_pool::create( + publisher, + fungible_asset::mint_ref_metadata(&mint_1), + fungible_asset::mint_ref_metadata(&mint_2), + is_stable, + ); + (pool, mint_1, mint_2) + } + + public fun create_fungible_asset(creator: &signer, name: vector): MintRef { + let token_metadata = &object::create_named_object(creator, name); + primary_fungible_store::create_primary_store_enabled_fungible_asset( + token_metadata, + option::none(), + string::utf8(name), + string::utf8(name), + 8, + string::utf8(b""), + string::utf8(b""), + ); + fungible_asset::generate_mint_ref(token_metadata) + } + +} diff --git a/testsuite/single_node_performance.py b/testsuite/single_node_performance.py index 194c669ea556f..116e6c641ab07 100755 --- a/testsuite/single_node_performance.py +++ b/testsuite/single_node_performance.py @@ -150,6 +150,12 @@ class RunGroupConfig: RunGroupConfig(expected_tps=7006, key=RunGroupKey("token-v2-ambassador-mint"), included_in=LAND_BLOCKING_AND_C | Flow.REPRESENTATIVE), RunGroupConfig(expected_tps=6946, key=RunGroupKey("token-v2-ambassador-mint", module_working_set_size=20), included_in=Flow.CONTINUOUS), + RunGroupConfig(expected_tps=1030, key=RunGroupKey("liquidity-pool-swap"), included_in=LAND_BLOCKING_AND_C | Flow.REPRESENTATIVE), + RunGroupConfig(expected_tps=4520, key=RunGroupKey("liquidity-pool-swap", module_working_set_size=20), included_in=Flow.CONTINUOUS), + + RunGroupConfig(expected_tps=970, key=RunGroupKey("liquidity-pool-swap-stable"), included_in=Flow.CONTINUOUS), + RunGroupConfig(expected_tps=4350, key=RunGroupKey("liquidity-pool-swap-stable", module_working_set_size=20), included_in=Flow.CONTINUOUS), + # fee payer sequentializes transactions today. in these tests module publisher is the fee payer, so larger number of modules tests throughput with multiple fee payers RunGroupConfig(expected_tps=3120, key=RunGroupKey("no-op-fee-payer"), included_in=LAND_BLOCKING_AND_C), RunGroupConfig(expected_tps=17747, key=RunGroupKey("no-op-fee-payer", module_working_set_size=50), included_in=Flow.CONTINUOUS), From 514bf17a7746ccb1bbc4bdc25408aeefe3bcd3de Mon Sep 17 00:00:00 2001 From: zhoujunma Date: Fri, 5 Apr 2024 17:48:52 -0700 Subject: [PATCH 17/36] parameterize jwk consensus config in genesis (#12618) * add jwk consensus config override in layout and stop putting google in genesis * add jwk consensus config override entry in genesis.yaml * initialize jwk consensus with a env var * undo terraform changes --- aptos-move/vm-genesis/src/lib.rs | 15 --------------- aptos-node/src/lib.rs | 12 ++++++++++-- crates/aptos-genesis/src/config.rs | 6 +++++- crates/aptos/src/genesis/mod.rs | 2 +- types/src/on_chain_config/jwk_consensus_config.rs | 8 +++++++- 5 files changed, 23 insertions(+), 20 deletions(-) diff --git a/aptos-move/vm-genesis/src/lib.rs b/aptos-move/vm-genesis/src/lib.rs index 1dfe710dad109..2980efdf0b535 100644 --- a/aptos-move/vm-genesis/src/lib.rs +++ b/aptos-move/vm-genesis/src/lib.rs @@ -629,21 +629,6 @@ fn initialize_keyless_accounts(session: &mut SessionExt, chain_id: ChainId) { ]), ); } - if !chain_id.id() > 100 { - exec_function( - session, - JWKS_MODULE_NAME, - "upsert_oidc_provider", - vec![], - serialize_values(&vec![ - MoveValue::Signer(CORE_CODE_ADDRESS), - "https://accounts.google.com".to_string().as_move_value(), - "https://accounts.google.com/.well-known/openid-configuration" - .to_string() - .as_move_value(), - ]), - ); - } } fn create_accounts(session: &mut SessionExt, accounts: &[AccountBalance]) { diff --git a/aptos-node/src/lib.rs b/aptos-node/src/lib.rs index ac07e97d64481..073bca618a7bf 100644 --- a/aptos-node/src/lib.rs +++ b/aptos-node/src/lib.rs @@ -29,14 +29,14 @@ use aptos_jwk_consensus::start_jwk_consensus_runtime; use aptos_logger::{prelude::*, telemetry_log_writer::TelemetryLog, Level, LoggerFilterUpdater}; use aptos_safety_rules::safety_rules_manager::load_consensus_key_from_secure_storage; use aptos_state_sync_driver::driver_factory::StateSyncRuntimes; -use aptos_types::chain_id::ChainId; +use aptos_types::{chain_id::ChainId, on_chain_config::OnChainJWKConsensusConfig}; use aptos_validator_transaction_pool::VTxnPoolState; use clap::Parser; use futures::channel::mpsc; use hex::{FromHex, FromHexError}; use rand::{rngs::StdRng, SeedableRng}; use std::{ - fs, + env, fs, io::Write, path::{Path, PathBuf}, sync::{ @@ -529,6 +529,14 @@ where genesis_config.allow_new_validators = true; genesis_config.epoch_duration_secs = EPOCH_LENGTH_SECS; genesis_config.recurring_lockup_duration_secs = 7200; + genesis_config.jwk_consensus_config_override = match env::var("INITIALIZE_JWK_CONSENSUS") { + Ok(val) if val.as_str() == "1" => { + let config = OnChainJWKConsensusConfig::default_enabled(); + println!("Flag `INITIALIZE_JWK_CONSENSUS` detected, will enable JWK Consensus for all default OIDC providers in genesis: {:?}", config); + Some(config) + }, + _ => None, + }; }))) .with_randomize_first_validator_ports(random_ports); let (root_key, _genesis, genesis_waypoint, mut validators) = builder.build(rng)?; diff --git a/crates/aptos-genesis/src/config.rs b/crates/aptos-genesis/src/config.rs index 28fdc92e85957..5e39ce08c17ac 100644 --- a/crates/aptos-genesis/src/config.rs +++ b/crates/aptos-genesis/src/config.rs @@ -7,7 +7,7 @@ use aptos_types::{ account_address::{AccountAddress, AccountAddressWithChecks}, chain_id::ChainId, network_address::{DnsName, NetworkAddress, Protocol}, - on_chain_config::{OnChainConsensusConfig, OnChainExecutionConfig}, + on_chain_config::{OnChainConsensusConfig, OnChainExecutionConfig, OnChainJWKConsensusConfig}, transaction::authenticator::AuthenticationKey, }; use aptos_vm_genesis::{AccountBalance, EmployeePool, Validator, ValidatorWithCommissionRate}; @@ -73,6 +73,9 @@ pub struct Layout { /// Onchain Execution Config #[serde(default = "OnChainExecutionConfig::default_for_genesis")] pub on_chain_execution_config: OnChainExecutionConfig, + + /// An optional JWK consensus config to use, instead of `default_for_genesis()`. + pub jwk_consensus_config_override: Option, } impl Layout { @@ -112,6 +115,7 @@ impl Default for Layout { employee_vesting_period_duration: Some(5 * 60), // 5 minutes on_chain_consensus_config: OnChainConsensusConfig::default(), on_chain_execution_config: OnChainExecutionConfig::default_for_genesis(), + jwk_consensus_config_override: None, } } } diff --git a/crates/aptos/src/genesis/mod.rs b/crates/aptos/src/genesis/mod.rs index 1ca3e34297d74..f4f0fddd7c46e 100644 --- a/crates/aptos/src/genesis/mod.rs +++ b/crates/aptos/src/genesis/mod.rs @@ -302,7 +302,7 @@ pub fn fetch_genesis_info(git_options: GitOptions) -> CliTypedResult Self { Self::V1(ConfigV1 { - oidc_providers: vec![], + oidc_providers: vec![OIDCProvider { + name: "https://accounts.google.com".to_string(), + config_url: "https://accounts.google.com/.well-known/openid-configuration" + .to_string(), + }], }) } @@ -55,6 +59,8 @@ impl OnChainJWKConsensusConfig { } pub fn default_for_genesis() -> Self { + // Here it is supposed to use `default_enabled()`. + // Using an empty list instead to avoid DDoSing the CI infra or the actual providers. Self::V1(ConfigV1 { oidc_providers: vec![], }) From fec2fbe817df70e9c8ccb55fec52a568ec8586c5 Mon Sep 17 00:00:00 2001 From: Oliver He Date: Sat, 6 Apr 2024 02:54:19 -0400 Subject: [PATCH 18/36] Add the secure test jwk as a patch at genesis (#12799) * Add the secure test jwk as a patch at genesis * add test * add doc for where secret key lives --- aptos-move/vm-genesis/src/lib.rs | 26 +++++++++++- .../src/jwks/jwk_consensus_basic.rs | 22 ++++++++-- .../src/jwks/jwk_consensus_per_issuer.rs | 34 +++++++++++----- .../jwk_consensus_provider_change_mind.rs | 17 ++++++-- testsuite/smoke-test/src/keyless.rs | 25 ++++++++++++ types/src/jwks/jwk/mod.rs | 6 +++ types/src/jwks/mod.rs | 1 + types/src/jwks/patch/mod.rs | 40 +++++++++++++++++++ types/src/jwks/rsa/mod.rs | 11 +++++ 9 files changed, 164 insertions(+), 18 deletions(-) create mode 100644 types/src/jwks/patch/mod.rs diff --git a/aptos-move/vm-genesis/src/lib.rs b/aptos-move/vm-genesis/src/lib.rs index 2980efdf0b535..2e16bbe93cdbc 100644 --- a/aptos-move/vm-genesis/src/lib.rs +++ b/aptos-move/vm-genesis/src/lib.rs @@ -21,8 +21,14 @@ use aptos_types::{ account_config::{self, aptos_test_root_address, events::NewEpochEvent, CORE_CODE_ADDRESS}, chain_id::ChainId, contract_event::{ContractEvent, ContractEventV1}, - keyless, - keyless::{Groth16VerificationKey, DEVNET_VERIFICATION_KEY, KEYLESS_ACCOUNT_MODULE_NAME}, + jwks::{ + patch::{PatchJWKMoveStruct, PatchUpsertJWK}, + rsa::RSA_JWK, + }, + keyless::{ + self, test_utils::get_sample_iss, Groth16VerificationKey, DEVNET_VERIFICATION_KEY, + KEYLESS_ACCOUNT_MODULE_NAME, + }, move_utils::as_move_value::AsMoveValue, on_chain_config::{ FeatureFlag, Features, GasScheduleV2, OnChainConsensusConfig, OnChainExecutionConfig, @@ -628,6 +634,22 @@ fn initialize_keyless_accounts(session: &mut SessionExt, chain_id: ChainId) { vk.as_move_value(), ]), ); + + let patch: PatchJWKMoveStruct = PatchUpsertJWK { + issuer: get_sample_iss(), + jwk: RSA_JWK::secure_test_jwk().into(), + } + .into(); + exec_function( + session, + JWKS_MODULE_NAME, + "set_patches", + vec![], + serialize_values(&vec![ + MoveValue::Signer(CORE_CODE_ADDRESS), + MoveValue::Vector(vec![patch.as_move_value()]), + ]), + ); } } diff --git a/testsuite/smoke-test/src/jwks/jwk_consensus_basic.rs b/testsuite/smoke-test/src/jwks/jwk_consensus_basic.rs index 030a45a50132b..f059cbf527360 100644 --- a/testsuite/smoke-test/src/jwks/jwk_consensus_basic.rs +++ b/testsuite/smoke-test/src/jwks/jwk_consensus_basic.rs @@ -14,7 +14,13 @@ use crate::{ use aptos_forge::{NodeExt, Swarm, SwarmExt}; use aptos_logger::{debug, info}; use aptos_types::{ - jwks::{jwk::JWK, rsa::RSA_JWK, unsupported::UnsupportedJWK, AllProvidersJWKs, ProviderJWKs}, + jwks::{ + jwk::{JWKMoveStruct, JWK}, + rsa::RSA_JWK, + unsupported::UnsupportedJWK, + AllProvidersJWKs, ProviderJWKs, + }, + keyless::test_utils::get_sample_iss, on_chain_config::{JWKConsensusConfigV1, OIDCProvider, OnChainJWKConsensusConfig}, }; use std::{sync::Arc, time::Duration}; @@ -43,12 +49,12 @@ async fn jwk_consensus_basic() { .await .expect("Epoch 2 taking too long to arrive!"); - info!("Initially the provider set is empty. So should be the JWK map."); + info!("Initially the provider set is empty. The JWK map should have the secure test jwk added via a patch at genesis."); sleep(Duration::from_secs(10)).await; let patched_jwks = get_patched_jwks(&client).await; debug!("patched_jwks={:?}", patched_jwks); - assert!(patched_jwks.jwks.entries.is_empty()); + assert!(patched_jwks.jwks.entries.len() == 1); info!("Adding some providers."); let (provider_alice, provider_bob) = @@ -107,6 +113,11 @@ async fn jwk_consensus_basic() { )) .into()], }, + ProviderJWKs { + issuer: get_sample_iss().into_bytes(), + version: 0, + jwks: vec![JWKMoveStruct::from(RSA_JWK::secure_test_jwk())], + }, ] }, patched_jwks.jwks @@ -142,6 +153,11 @@ async fn jwk_consensus_basic() { )) .into()], }, + ProviderJWKs { + issuer: get_sample_iss().into_bytes(), + version: 0, + jwks: vec![JWKMoveStruct::from(RSA_JWK::secure_test_jwk())], + }, ] }, patched_jwks.jwks diff --git a/testsuite/smoke-test/src/jwks/jwk_consensus_per_issuer.rs b/testsuite/smoke-test/src/jwks/jwk_consensus_per_issuer.rs index 7a27972d3c5e2..3b5dfcdf73628 100644 --- a/testsuite/smoke-test/src/jwks/jwk_consensus_per_issuer.rs +++ b/testsuite/smoke-test/src/jwks/jwk_consensus_per_issuer.rs @@ -14,7 +14,13 @@ use crate::{ use aptos_forge::{NodeExt, Swarm, SwarmExt}; use aptos_logger::{debug, info}; use aptos_types::{ - jwks::{jwk::JWK, unsupported::UnsupportedJWK, AllProvidersJWKs, ProviderJWKs}, + jwks::{ + jwk::{JWKMoveStruct, JWK}, + rsa::RSA_JWK, + unsupported::UnsupportedJWK, + AllProvidersJWKs, ProviderJWKs, + }, + keyless::test_utils::get_sample_iss, on_chain_config::{JWKConsensusConfigV1, OIDCProvider, OnChainJWKConsensusConfig}, }; use std::{sync::Arc, time::Duration}; @@ -44,12 +50,12 @@ async fn jwk_consensus_per_issuer() { .await .expect("Epoch 2 taking too long to arrive!"); - info!("Initially the provider set is empty. So should be the JWK map."); + info!("Initially the provider set is empty. The JWK map should have the secure test jwk added via a patch at genesis."); sleep(Duration::from_secs(10)).await; let patched_jwks = get_patched_jwks(&client).await; debug!("patched_jwks={:?}", patched_jwks); - assert!(patched_jwks.jwks.entries.is_empty()); + assert!(patched_jwks.jwks.entries.len() == 1); info!("Adding some providers, one seriously equivocating, the other well behaving."); let (provider_alice, provider_bob) = @@ -84,13 +90,21 @@ async fn jwk_consensus_per_issuer() { debug!("patched_jwks={:?}", patched_jwks); assert_eq!( AllProvidersJWKs { - entries: vec![ProviderJWKs { - issuer: b"https://bob.dev".to_vec(), - version: 1, - jwks: vec![ - JWK::Unsupported(UnsupportedJWK::new_with_payload("\"BOB_JWK_V0\"")).into() - ], - }] + entries: vec![ + ProviderJWKs { + issuer: b"https://bob.dev".to_vec(), + version: 1, + jwks: vec![JWK::Unsupported(UnsupportedJWK::new_with_payload( + "\"BOB_JWK_V0\"" + )) + .into()], + }, + ProviderJWKs { + issuer: get_sample_iss().into_bytes(), + version: 0, + jwks: vec![JWKMoveStruct::from(RSA_JWK::secure_test_jwk())], + }, + ] }, patched_jwks.jwks ); diff --git a/testsuite/smoke-test/src/jwks/jwk_consensus_provider_change_mind.rs b/testsuite/smoke-test/src/jwks/jwk_consensus_provider_change_mind.rs index 9f93391cb8499..4a0e105bcc86e 100644 --- a/testsuite/smoke-test/src/jwks/jwk_consensus_provider_change_mind.rs +++ b/testsuite/smoke-test/src/jwks/jwk_consensus_provider_change_mind.rs @@ -14,7 +14,13 @@ use crate::{ use aptos_forge::{NodeExt, Swarm, SwarmExt}; use aptos_logger::{debug, info}; use aptos_types::{ - jwks::{jwk::JWK, unsupported::UnsupportedJWK, AllProvidersJWKs, ProviderJWKs}, + jwks::{ + jwk::{JWKMoveStruct, JWK}, + rsa::RSA_JWK, + unsupported::UnsupportedJWK, + AllProvidersJWKs, ProviderJWKs, + }, + keyless::test_utils::get_sample_iss, on_chain_config::{JWKConsensusConfigV1, OIDCProvider, OnChainJWKConsensusConfig}, }; use std::{sync::Arc, time::Duration}; @@ -46,12 +52,12 @@ async fn jwk_consensus_provider_change_mind() { .await .expect("Epoch 2 taking too long to arrive!"); - info!("Initially the provider set is empty. So should be the ObservedJWKs."); + info!("Initially the provider set is empty. The JWK map should have the secure test jwk added via a patch at genesis."); sleep(Duration::from_secs(10)).await; let patched_jwks = get_patched_jwks(&client).await; debug!("patched_jwks={:?}", patched_jwks); - assert!(patched_jwks.jwks.entries.is_empty()); + assert!(patched_jwks.jwks.entries.len() == 1); info!("Adding some providers."); let (provider_alice, provider_bob) = @@ -103,6 +109,11 @@ async fn jwk_consensus_provider_change_mind() { )) .into()], }, + ProviderJWKs { + issuer: get_sample_iss().into_bytes(), + version: 0, + jwks: vec![JWKMoveStruct::from(RSA_JWK::secure_test_jwk())], + }, ] }, patched_jwks.jwks diff --git a/testsuite/smoke-test/src/keyless.rs b/testsuite/smoke-test/src/keyless.rs index a4449ee945424..45d33efb57434 100644 --- a/testsuite/smoke-test/src/keyless.rs +++ b/testsuite/smoke-test/src/keyless.rs @@ -57,6 +57,31 @@ async fn test_keyless_oidc_txn_verifies() { } } +#[tokio::test] +async fn test_keyless_secure_test_jwk_initialized_at_genesis() { + let (swarm, _cli, _faucet) = SwarmBuilder::new_local(1) + .with_aptos() + .build_with_cli(0) + .await; + let client = swarm.validators().next().unwrap().rest_client(); + swarm + .wait_for_all_nodes_to_catchup_to_epoch(2, Duration::from_secs(60)) + .await + .expect("Epoch 2 taking too long to come!"); + + let patched_jwks = get_latest_jwkset(&client).await; + debug!("patched_jwks={:?}", patched_jwks); + let iss = get_sample_iss(); + let expected_providers_jwks = AllProvidersJWKs { + entries: vec![ProviderJWKs { + issuer: iss.into_bytes(), + version: 0, + jwks: vec![JWKMoveStruct::from(RSA_JWK::secure_test_jwk())], + }], + }; + assert_eq!(expected_providers_jwks, patched_jwks.jwks); +} + #[tokio::test] async fn test_keyless_oidc_txn_with_bad_jwt_sig() { let (tw_sk, config, jwk, mut swarm, _) = setup_local_net().await; diff --git a/types/src/jwks/jwk/mod.rs b/types/src/jwks/jwk/mod.rs index 011660d566072..f5d692162b815 100644 --- a/types/src/jwks/jwk/mod.rs +++ b/types/src/jwks/jwk/mod.rs @@ -40,6 +40,12 @@ impl AsMoveValue for JWKMoveStruct { } } +impl From for JWKMoveStruct { + fn from(rsa_jwk: RSA_JWK) -> Self { + JWKMoveStruct::from(JWK::RSA(rsa_jwk)) + } +} + /// The JWK type that can be converted from/to `JWKMoveStruct` but easier to use in rust. #[derive(Debug, PartialEq, Eq)] pub enum JWK { diff --git a/types/src/jwks/mod.rs b/types/src/jwks/mod.rs index d97db15234684..53477915d4eec 100644 --- a/types/src/jwks/mod.rs +++ b/types/src/jwks/mod.rs @@ -24,6 +24,7 @@ use std::{ }; pub mod jwk; +pub mod patch; pub mod rsa; pub mod unsupported; diff --git a/types/src/jwks/patch/mod.rs b/types/src/jwks/patch/mod.rs new file mode 100644 index 0000000000000..6cbaaa660e082 --- /dev/null +++ b/types/src/jwks/patch/mod.rs @@ -0,0 +1,40 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +// Copyright © Aptos Foundation + +use crate::{ + jwks::jwk::JWKMoveStruct, + move_any::{Any as MoveAny, AsMoveAny}, + move_utils::as_move_value::AsMoveValue, +}; +use move_core_types::value::{MoveStruct, MoveValue}; +use serde::{Deserialize, Serialize}; + +pub struct PatchJWKMoveStruct { + pub variant: MoveAny, +} + +impl AsMoveValue for PatchJWKMoveStruct { + fn as_move_value(&self) -> MoveValue { + MoveValue::Struct(MoveStruct::Runtime(vec![self.variant.as_move_value()])) + } +} + +impl From for PatchJWKMoveStruct { + fn from(patch: PatchUpsertJWK) -> Self { + Self { + variant: patch.as_move_any(), + } + } +} + +#[derive(Clone, Eq, PartialEq, Serialize, Deserialize)] +pub struct PatchUpsertJWK { + pub issuer: String, + pub jwk: JWKMoveStruct, +} + +impl AsMoveAny for PatchUpsertJWK { + const MOVE_TYPE_NAME: &'static str = "0x1::jwks::PatchUpsertJWK"; +} diff --git a/types/src/jwks/rsa/mod.rs b/types/src/jwks/rsa/mod.rs index 29561d2dece1b..6017e7c5df1b2 100644 --- a/types/src/jwks/rsa/mod.rs +++ b/types/src/jwks/rsa/mod.rs @@ -47,6 +47,17 @@ impl RSA_JWK { } } + // The private key to this JWK is found under INTERNAL_TEST_OIDC_PROVIDER_PRIVATE_KEY in aptos-keyless-prod in gcloud secrets + pub fn secure_test_jwk() -> RSA_JWK { + RSA_JWK { + kid:"test-rsa".to_owned(), + kty:"RSA".to_owned(), + alg:"RS256".to_owned(), + e:"AQAB".to_owned(), + n:"y5Efs1ZzisLLKCARSvTztgWj5JFP3778dZWt-od78fmOZFxem3a_aYbOXSJToRp862do0PxJ4PDMpmqwV5f7KplFI6NswQV-WPufQH8IaHXZtuPdCjPOcHybcDiLkO12d0dG6iZQUzypjAJf63APcadio-4JDNWlGC5_Ow_XQ9lIY71kTMiT9lkCCd0ZxqEifGtnJe5xSoZoaMRKrvlOw-R6iVjLUtPAk5hyUX95LDKxwAR-oshnj7gmATejga2EvH9ozdn3M8Go11PSDa04OQxPcA25OoDTfxLvT28LRpSXrbmUWZ-O_lGtDl3ZAtjIguYGEobTk4N11eRssC95Cw".to_owned() + } + } + pub fn verify_signature(&self, jwt_token: &str) -> Result> { let mut validation = Validation::new(Algorithm::RS256); validation.validate_exp = false; From c807593fe58b7517e25b1444919dfc8d72cdd497 Mon Sep 17 00:00:00 2001 From: "Daniel Porteous (dport)" Date: Sat, 6 Apr 2024 14:27:56 +0100 Subject: [PATCH 19/36] Properly pin buf proto gen tools for TS (#11769) --- protos/buf.ts.gen.yaml | 2 +- protos/scripts/install_deps.sh | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/protos/buf.ts.gen.yaml b/protos/buf.ts.gen.yaml index e9ed7bce3349f..b5919192ced94 100644 --- a/protos/buf.ts.gen.yaml +++ b/protos/buf.ts.gen.yaml @@ -2,7 +2,7 @@ version: v1 managed: enabled: true plugins: - - plugin: buf.build/community/stephenh-ts-proto + - plugin: buf.build/community/stephenh-ts-proto:v1.167.9 out: typescript/src opt: # See an explanation of these options here: diff --git a/protos/scripts/install_deps.sh b/protos/scripts/install_deps.sh index 622df71f70040..60f0e422ba607 100755 --- a/protos/scripts/install_deps.sh +++ b/protos/scripts/install_deps.sh @@ -1,6 +1,8 @@ #!/bin/sh # This assumes that cargo, pnpm, poetry, buf, and protoc are already installed. +# The TS plugins are pulled automatically since we depend on them directly from +# the buf.build community plugin registry. # For generating Rust code cargo install --version 0.2.3 protoc-gen-prost @@ -8,10 +10,6 @@ cargo install --version 0.2.3 protoc-gen-prost-serde cargo install --version 0.3.1 protoc-gen-prost-crate cargo install --version 0.3.0 protoc-gen-tonic -# For generating TS code -pnpm install -g protoc-gen-ts@0.8.7 - # For generating Python code cd python poetry install - From 220e4f712cb53bd586be8232481877d25cf2484b Mon Sep 17 00:00:00 2001 From: "Daniel Porteous (dport)" Date: Mon, 8 Apr 2024 18:07:38 +0100 Subject: [PATCH 20/36] [Data Service] Push metrics parameterized by identifier, not API key name + email (#12547) --- .../indexer-grpc-data-service/src/metrics.rs | 19 ++++---- .../indexer-grpc-data-service/src/service.rs | 47 ++++++------------- .../indexer-grpc-utils/src/constants.rs | 5 +- .../indexer-grpc-utils/src/counters.rs | 5 +- 4 files changed, 28 insertions(+), 48 deletions(-) diff --git a/ecosystem/indexer-grpc/indexer-grpc-data-service/src/metrics.rs b/ecosystem/indexer-grpc/indexer-grpc-data-service/src/metrics.rs index a605f4a313d78..ad3d23bb6257c 100644 --- a/ecosystem/indexer-grpc/indexer-grpc-data-service/src/metrics.rs +++ b/ecosystem/indexer-grpc/indexer-grpc-data-service/src/metrics.rs @@ -7,12 +7,15 @@ use aptos_metrics_core::{ }; use once_cell::sync::Lazy; +// The `identifier` label at the time of writing (2024-04-08) is always the +// application ID, a globally unique ID. + /// Latest processed transaction version. pub static LATEST_PROCESSED_VERSION: Lazy = Lazy::new(|| { register_int_gauge_vec!( "indexer_grpc_data_service_with_user_latest_processed_version", "Latest processed transaction version", - &["request_token", "email", "processor"], + &["identifier", "processor"], ) .unwrap() }); @@ -22,7 +25,7 @@ pub static PROCESSED_VERSIONS_COUNT: Lazy = Lazy::new(|| { register_int_counter_vec!( "indexer_grpc_data_service_with_user_processed_versions", "Number of transactions that have been processed by data service", - &["request_token", "email", "processor"], + &["identifier", "processor"], ) .unwrap() }); @@ -42,7 +45,7 @@ pub static PROCESSED_LATENCY_IN_SECS: Lazy = Lazy::new(|| { register_gauge_vec!( "indexer_grpc_data_service_with_user_latest_data_latency_in_secs", "Latency of data service based on latest processed transaction", - &["request_token", "email", "processor"], + &["identifier", "processor"], ) .unwrap() }); @@ -52,7 +55,7 @@ pub static PROCESSED_LATENCY_IN_SECS_ALL: Lazy = Lazy::new(|| { register_histogram_vec!( "indexer_grpc_data_service_latest_data_latency_in_secs_all", "Latency of data service based on latest processed transaction", - &["request_token"] + &[] ) .unwrap() }); @@ -62,7 +65,7 @@ pub static PROCESSED_BATCH_SIZE: Lazy = Lazy::new(|| { register_int_gauge_vec!( "indexer_grpc_data_service_with_user_processed_batch_size", "Size of latest processed batch by data service", - &["request_token", "email", "processor"], + &["identifier", "processor"], ) .unwrap() }); @@ -72,7 +75,7 @@ pub static CONNECTION_COUNT: Lazy = Lazy::new(|| { register_int_counter_vec!( "indexer_grpc_data_service_connection_count_v2", "Count of connections that data service has established", - &["request_token", "email", "processor"], + &["identifier", "processor"], ) .unwrap() }); @@ -82,7 +85,7 @@ pub static SHORT_CONNECTION_COUNT: Lazy = Lazy::new(|| { register_int_counter_vec!( "indexer_grpc_data_service_short_connection_by_user_processor_count", "Count of the short connections; i.e., < 10 seconds", - &["request_token", "email", "processor"], + &["identifier", "processor"], ) .unwrap() }); @@ -93,7 +96,7 @@ pub static BYTES_READY_TO_TRANSFER_FROM_SERVER: Lazy = Lazy::new( register_int_counter_vec!( "indexer_grpc_data_service_bytes_ready_to_transfer_from_server", "Count of bytes ready to transfer to the client", - &["request_token", "email", "processor"], + &["identifier", "processor"], ) .unwrap() }); diff --git a/ecosystem/indexer-grpc/indexer-grpc-data-service/src/service.rs b/ecosystem/indexer-grpc/indexer-grpc-data-service/src/service.rs index 4c9435bde3e0e..aa6bb7b063b01 100644 --- a/ecosystem/indexer-grpc/indexer-grpc-data-service/src/service.rs +++ b/ecosystem/indexer-grpc/indexer-grpc-data-service/src/service.rs @@ -62,9 +62,9 @@ const RESPONSE_CHANNEL_SEND_TIMEOUT: Duration = Duration::from_secs(120); const SHORT_CONNECTION_DURATION_IN_SECS: u64 = 10; -const REQUEST_HEADER_APTOS_EMAIL_HEADER: &str = "x-aptos-email"; -const REQUEST_HEADER_APTOS_USER_CLASSIFICATION_HEADER: &str = "x-aptos-user-classification"; -const REQUEST_HEADER_APTOS_API_KEY_NAME: &str = "x-aptos-api-key-name"; +/// This comes from API Gateway. The identifier uniquely identifies the requester, which +/// in the case of indexer-grpc is always an application. +const REQUEST_HEADER_APTOS_IDENTIFIER: &str = "x-aptos-identifier"; const RESPONSE_HEADER_APTOS_CONNECTION_ID_HEADER: &str = "x-aptos-connection-id"; const SERVICE_TYPE: &str = "data_service"; @@ -141,8 +141,7 @@ impl RawData for RawDataServerWrapper { }; CONNECTION_COUNT .with_label_values(&[ - &request_metadata.request_api_key_name, - &request_metadata.request_email, + &request_metadata.request_identifier, &request_metadata.processor_name, ]) .inc(); @@ -349,12 +348,9 @@ async fn get_data_in_task( Ok(TransactionsDataStatus::AheadOfCache) => { info!( start_version = start_version, - request_name = request_metadata.processor_name.as_str(), - request_email = request_metadata.request_email.as_str(), - request_api_key_name = request_metadata.request_api_key_name.as_str(), + request_identifier = request_metadata.request_identifier.as_str(), processor_name = request_metadata.processor_name.as_str(), connection_id = request_metadata.request_connection_id.as_str(), - request_user_classification = request_metadata.request_user_classification.as_str(), duration_in_secs = current_batch_start_time.elapsed().as_secs_f64(), service_type = SERVICE_TYPE, "[Data Service] Requested data is ahead of cache. Sleeping for {} ms.", @@ -513,8 +509,7 @@ async fn data_fetcher_task( .sum::(); BYTES_READY_TO_TRANSFER_FROM_SERVER .with_label_values(&[ - &request_metadata.request_api_key_name, - &request_metadata.request_email, + &request_metadata.request_identifier, &request_metadata.processor_name, ]) .inc_by(bytes_ready_to_transfer as u64); @@ -542,36 +537,32 @@ async fn data_fetcher_task( Ok(_) => { PROCESSED_BATCH_SIZE .with_label_values(&[ - request_metadata.request_api_key_name.as_str(), - request_metadata.request_email.as_str(), + request_metadata.request_identifier.as_str(), request_metadata.processor_name.as_str(), ]) .set(current_batch_size as i64); // TODO: Reasses whether this metric useful LATEST_PROCESSED_VERSION_OLD .with_label_values(&[ - request_metadata.request_api_key_name.as_str(), - request_metadata.request_email.as_str(), + request_metadata.request_identifier.as_str(), request_metadata.processor_name.as_str(), ]) .set(end_of_batch_version as i64); PROCESSED_VERSIONS_COUNT .with_label_values(&[ - request_metadata.request_api_key_name.as_str(), - request_metadata.request_email.as_str(), + request_metadata.request_identifier.as_str(), request_metadata.processor_name.as_str(), ]) .inc_by(current_batch_size as u64); if let Some(data_latency_in_secs) = data_latency_in_secs { PROCESSED_LATENCY_IN_SECS .with_label_values(&[ - request_metadata.request_api_key_name.as_str(), - request_metadata.request_email.as_str(), + request_metadata.request_identifier.as_str(), request_metadata.processor_name.as_str(), ]) .set(data_latency_in_secs); PROCESSED_LATENCY_IN_SECS_ALL - .with_label_values(&[request_metadata.request_user_classification.as_str()]) + .with_label_values(&[]) .observe(data_latency_in_secs); } }, @@ -589,13 +580,9 @@ async fn data_fetcher_task( current_version = end_of_batch_version + 1; } info!( - request_name = request_metadata.processor_name.as_str(), - request_email = request_metadata.request_email.as_str(), - request_api_key_name = request_metadata.request_api_key_name.as_str(), + request_identifier = request_metadata.request_identifier.as_str(), processor_name = request_metadata.processor_name.as_str(), connection_id = request_metadata.request_connection_id.as_str(), - request_user_classification = request_metadata.request_user_classification.as_str(), - request_user_classification = request_metadata.request_user_classification.as_str(), service_type = SERVICE_TYPE, "[Data Service] Client disconnected." ); @@ -603,8 +590,7 @@ async fn data_fetcher_task( if start_time.elapsed().as_secs() < SHORT_CONNECTION_DURATION_IN_SECS { SHORT_CONNECTION_COUNT .with_label_values(&[ - request_metadata.request_api_key_name.as_str(), - request_metadata.request_email.as_str(), + request_metadata.request_identifier.as_str(), request_metadata.processor_name.as_str(), ]) .inc(); @@ -869,12 +855,7 @@ fn get_request_metadata( req: &Request, ) -> tonic::Result { let request_metadata_pairs = vec![ - ("request_api_key_name", REQUEST_HEADER_APTOS_API_KEY_NAME), - ("request_email", REQUEST_HEADER_APTOS_EMAIL_HEADER), - ( - "request_user_classification", - REQUEST_HEADER_APTOS_USER_CLASSIFICATION_HEADER, - ), + ("request_identifier", REQUEST_HEADER_APTOS_IDENTIFIER), ("request_token", GRPC_AUTH_TOKEN_HEADER), ("processor_name", GRPC_REQUEST_NAME_HEADER), ]; diff --git a/ecosystem/indexer-grpc/indexer-grpc-utils/src/constants.rs b/ecosystem/indexer-grpc/indexer-grpc-utils/src/constants.rs index d0ed060203438..5d06abeaf18f5 100644 --- a/ecosystem/indexer-grpc/indexer-grpc-utils/src/constants.rs +++ b/ecosystem/indexer-grpc/indexer-grpc-utils/src/constants.rs @@ -17,9 +17,8 @@ pub const MESSAGE_SIZE_LIMIT: usize = 1024 * 1024 * 15; #[derive(Clone, Serialize, Deserialize, Debug)] pub struct IndexerGrpcRequestMetadata { pub processor_name: String, - pub request_email: String, - pub request_user_classification: String, - pub request_api_key_name: String, + /// See `REQUEST_HEADER_APTOS_IDENTIFIER` for more information. + pub request_identifier: String, pub request_connection_id: String, // Token is no longer needed behind api gateway. #[deprecated] diff --git a/ecosystem/indexer-grpc/indexer-grpc-utils/src/counters.rs b/ecosystem/indexer-grpc/indexer-grpc-utils/src/counters.rs index 394d34c9b0f0e..434bdb5cf613c 100644 --- a/ecosystem/indexer-grpc/indexer-grpc-utils/src/counters.rs +++ b/ecosystem/indexer-grpc/indexer-grpc-utils/src/counters.rs @@ -278,12 +278,9 @@ pub fn log_grpc_step( duration_in_secs, size_in_bytes, // Request metadata variables - request_name = &request_metadata.processor_name, - request_email = &request_metadata.request_email, - request_api_key_name = &request_metadata.request_api_key_name, + request_identifier = &request_metadata.request_identifier, processor_name = &request_metadata.processor_name, connection_id = &request_metadata.request_connection_id, - request_user_classification = &request_metadata.request_user_classification, service_type, step = step.get_step(), "{}", From 728bf9b2d1dc7de6b3543dacaada677cae541d24 Mon Sep 17 00:00:00 2001 From: Aaron Gao Date: Wed, 17 Jan 2024 23:18:30 -0700 Subject: [PATCH 21/36] [event_v2] migrate 3 files add feature flags use feature_flag to switch --- ...ansaction_with_entry_function_payload.json | 18 + ...e_when_start_version_is_not_specified.json | 144 ++++ api/src/tests/multisig_transactions_test.rs | 9 +- .../src/components/feature_flags.rs | 3 + aptos-move/e2e-tests/src/executor.rs | 2 +- .../framework/aptos-framework/doc/account.md | 112 +++- .../aptos-framework/doc/aptos_account.md | 20 +- .../aptos-framework/doc/aptos_governance.md | 313 ++++++--- .../framework/aptos-framework/doc/block.md | 224 +++++-- .../framework/aptos-framework/doc/coin.md | 9 +- .../aptos-framework/doc/fungible_asset.md | 4 +- .../aptos-framework/doc/multisig_account.md | 496 +++++++++++++- .../framework/aptos-framework/doc/object.md | 61 +- .../aptos-framework/doc/reconfiguration.md | 50 +- .../framework/aptos-framework/doc/stake.md | 631 +++++++++++++++--- .../aptos-framework/doc/staking_contract.md | 617 +++++++++++++++-- .../framework/aptos-framework/doc/vesting.md | 603 ++++++++++++++++- .../framework/aptos-framework/doc/voting.md | 250 ++++++- .../aptos-framework/sources/account.move | 233 +++++-- .../sources/aptos_account.move | 13 +- .../sources/aptos_governance.move | 176 ++++- .../aptos-framework/sources/block.move | 69 +- .../aptos-framework/sources/coin.move | 8 +- .../sources/fungible_asset.move | 4 +- .../sources/multisig_account.move | 188 +++++- .../aptos-framework/sources/object.move | 27 +- .../sources/reconfiguration.move | 24 + .../aptos-framework/sources/stake.move | 233 ++++++- .../sources/staking_contract.move | 196 +++++- .../sources/staking_contract.spec.move | 126 ++-- .../aptos-framework/sources/vesting.move | 237 ++++++- .../aptos-framework/sources/voting.move | 202 +++++- .../aptos-token-objects/doc/collection.md | 90 ++- .../aptos-token-objects/doc/token.md | 122 +++- .../sources/collection.move | 97 ++- .../aptos-token-objects/sources/token.move | 93 ++- .../aptos-token/doc/token_event_store.md | 573 ++++++++++++++++ .../aptos-token/doc/token_transfers.md | 12 +- .../sources/token_event_store.move | 183 +++++ .../aptos-token/sources/token_transfers.move | 4 + .../framework/move-stdlib/doc/features.md | 60 ++ .../move-stdlib/sources/configs/features.move | 30 + .../veiled_coin/sources/veiled_coin.move | 2 +- types/src/on_chain_config/aptos_features.rs | 2 + 44 files changed, 5905 insertions(+), 665 deletions(-) diff --git a/api/goldens/aptos_api__tests__transactions_test__test_get_transactions_output_user_transaction_with_entry_function_payload.json b/api/goldens/aptos_api__tests__transactions_test__test_get_transactions_output_user_transaction_with_entry_function_payload.json index a5b7b1b2413f4..40c597d4f5b87 100644 --- a/api/goldens/aptos_api__tests__transactions_test__test_get_transactions_output_user_transaction_with_entry_function_payload.json +++ b/api/goldens/aptos_api__tests__transactions_test__test_get_transactions_output_user_transaction_with_entry_function_payload.json @@ -124,6 +124,24 @@ "epoch": "1", "round": "1", "events": [ + { + "guid": { + "creation_number": "0", + "account_address": "0x0" + }, + "sequence_number": "0", + "type": "0x1::block::NewBlock", + "data": { + "epoch": "1", + "failed_proposer_indices": [], + "hash": "", + "height": "1", + "previous_block_votes_bitvec": "0x00", + "proposer": "0x66b22b7465af92a9dc8d07d2878716d9dffbbb280830a7d8cf80334b5da812ef", + "round": "1", + "time_microseconds": "500000" + } + }, { "guid": { "creation_number": "3", diff --git a/api/goldens/aptos_api__tests__transactions_test__test_get_transactions_returns_last_page_when_start_version_is_not_specified.json b/api/goldens/aptos_api__tests__transactions_test__test_get_transactions_returns_last_page_when_start_version_is_not_specified.json index cf42a4ebd8a82..428b21def2d19 100644 --- a/api/goldens/aptos_api__tests__transactions_test__test_get_transactions_returns_last_page_when_start_version_is_not_specified.json +++ b/api/goldens/aptos_api__tests__transactions_test__test_get_transactions_returns_last_page_when_start_version_is_not_specified.json @@ -129,6 +129,24 @@ "epoch": "1", "round": "1", "events": [ + { + "guid": { + "creation_number": "0", + "account_address": "0x0" + }, + "sequence_number": "0", + "type": "0x1::block::NewBlock", + "data": { + "epoch": "1", + "failed_proposer_indices": [], + "hash": "", + "height": "13", + "previous_block_votes_bitvec": "0x00", + "proposer": "0x66b22b7465af92a9dc8d07d2878716d9dffbbb280830a7d8cf80334b5da812ef", + "round": "1", + "time_microseconds": "6500000" + } + }, { "guid": { "creation_number": "3", @@ -465,6 +483,24 @@ "epoch": "1", "round": "1", "events": [ + { + "guid": { + "creation_number": "0", + "account_address": "0x0" + }, + "sequence_number": "0", + "type": "0x1::block::NewBlock", + "data": { + "epoch": "1", + "failed_proposer_indices": [], + "hash": "", + "height": "14", + "previous_block_votes_bitvec": "0x00", + "proposer": "0x66b22b7465af92a9dc8d07d2878716d9dffbbb280830a7d8cf80334b5da812ef", + "round": "1", + "time_microseconds": "7000000" + } + }, { "guid": { "creation_number": "3", @@ -801,6 +837,24 @@ "epoch": "1", "round": "1", "events": [ + { + "guid": { + "creation_number": "0", + "account_address": "0x0" + }, + "sequence_number": "0", + "type": "0x1::block::NewBlock", + "data": { + "epoch": "1", + "failed_proposer_indices": [], + "hash": "", + "height": "15", + "previous_block_votes_bitvec": "0x00", + "proposer": "0x66b22b7465af92a9dc8d07d2878716d9dffbbb280830a7d8cf80334b5da812ef", + "round": "1", + "time_microseconds": "7500000" + } + }, { "guid": { "creation_number": "3", @@ -1137,6 +1191,24 @@ "epoch": "1", "round": "1", "events": [ + { + "guid": { + "creation_number": "0", + "account_address": "0x0" + }, + "sequence_number": "0", + "type": "0x1::block::NewBlock", + "data": { + "epoch": "1", + "failed_proposer_indices": [], + "hash": "", + "height": "16", + "previous_block_votes_bitvec": "0x00", + "proposer": "0x66b22b7465af92a9dc8d07d2878716d9dffbbb280830a7d8cf80334b5da812ef", + "round": "1", + "time_microseconds": "8000000" + } + }, { "guid": { "creation_number": "3", @@ -1473,6 +1545,24 @@ "epoch": "1", "round": "1", "events": [ + { + "guid": { + "creation_number": "0", + "account_address": "0x0" + }, + "sequence_number": "0", + "type": "0x1::block::NewBlock", + "data": { + "epoch": "1", + "failed_proposer_indices": [], + "hash": "", + "height": "17", + "previous_block_votes_bitvec": "0x00", + "proposer": "0x66b22b7465af92a9dc8d07d2878716d9dffbbb280830a7d8cf80334b5da812ef", + "round": "1", + "time_microseconds": "8500000" + } + }, { "guid": { "creation_number": "3", @@ -1809,6 +1899,24 @@ "epoch": "1", "round": "1", "events": [ + { + "guid": { + "creation_number": "0", + "account_address": "0x0" + }, + "sequence_number": "0", + "type": "0x1::block::NewBlock", + "data": { + "epoch": "1", + "failed_proposer_indices": [], + "hash": "", + "height": "18", + "previous_block_votes_bitvec": "0x00", + "proposer": "0x66b22b7465af92a9dc8d07d2878716d9dffbbb280830a7d8cf80334b5da812ef", + "round": "1", + "time_microseconds": "9000000" + } + }, { "guid": { "creation_number": "3", @@ -2145,6 +2253,24 @@ "epoch": "1", "round": "1", "events": [ + { + "guid": { + "creation_number": "0", + "account_address": "0x0" + }, + "sequence_number": "0", + "type": "0x1::block::NewBlock", + "data": { + "epoch": "1", + "failed_proposer_indices": [], + "hash": "", + "height": "19", + "previous_block_votes_bitvec": "0x00", + "proposer": "0x66b22b7465af92a9dc8d07d2878716d9dffbbb280830a7d8cf80334b5da812ef", + "round": "1", + "time_microseconds": "9500000" + } + }, { "guid": { "creation_number": "3", @@ -2481,6 +2607,24 @@ "epoch": "1", "round": "1", "events": [ + { + "guid": { + "creation_number": "0", + "account_address": "0x0" + }, + "sequence_number": "0", + "type": "0x1::block::NewBlock", + "data": { + "epoch": "1", + "failed_proposer_indices": [], + "hash": "", + "height": "20", + "previous_block_votes_bitvec": "0x00", + "proposer": "0x66b22b7465af92a9dc8d07d2878716d9dffbbb280830a7d8cf80334b5da812ef", + "round": "1", + "time_microseconds": "10000000" + } + }, { "guid": { "creation_number": "3", diff --git a/api/src/tests/multisig_transactions_test.rs b/api/src/tests/multisig_transactions_test.rs index 5b6c0fbec6ef2..b02c5b0c976fb 100644 --- a/api/src/tests/multisig_transactions_test.rs +++ b/api/src/tests/multisig_transactions_test.rs @@ -367,12 +367,11 @@ async fn test_multisig_transaction_simulation() { let withdraw_event = &simulation_resp["events"].as_array().unwrap()[0]; assert_eq!( withdraw_event["type"].as_str().unwrap(), - "0x1::coin::WithdrawEvent" + "0x1::coin::Withdraw<0x1::aptos_coin::AptosCoin>" ); - let withdraw_from_account = AccountAddress::from_hex_literal( - withdraw_event["guid"]["account_address"].as_str().unwrap(), - ) - .unwrap(); + let withdraw_from_account = + AccountAddress::from_hex_literal(withdraw_event["data"]["account"].as_str().unwrap()) + .unwrap(); let withdrawn_amount = withdraw_event["data"]["amount"].as_str().unwrap(); assert_eq!(withdraw_from_account, multisig_account); assert_eq!(withdrawn_amount, "1000"); diff --git a/aptos-move/aptos-release-builder/src/components/feature_flags.rs b/aptos-move/aptos-release-builder/src/components/feature_flags.rs index 6d1ddce49f14d..4800da2c85d37 100644 --- a/aptos-move/aptos-release-builder/src/components/feature_flags.rs +++ b/aptos-move/aptos-release-builder/src/components/feature_flags.rs @@ -107,6 +107,7 @@ pub enum FeatureFlag { KeylessAccountsWithPasskeys, MultisigV2Enhancement, DelegationPoolAllowlisting, + ModuleEventMigration, } fn generate_features_blob(writer: &CodeWriter, data: &[u64]) { @@ -270,6 +271,7 @@ impl From for AptosFeatureFlag { FeatureFlag::DelegationPoolAllowlisting => { AptosFeatureFlag::DELEGATION_POOL_ALLOWLISTING }, + FeatureFlag::ModuleEventMigration => AptosFeatureFlag::MODULE_EVENT_MIGRATION, } } } @@ -362,6 +364,7 @@ impl From for FeatureFlag { AptosFeatureFlag::DELEGATION_POOL_ALLOWLISTING => { FeatureFlag::DelegationPoolAllowlisting }, + AptosFeatureFlag::MODULE_EVENT_MIGRATION => FeatureFlag::ModuleEventMigration, } } } diff --git a/aptos-move/e2e-tests/src/executor.rs b/aptos-move/e2e-tests/src/executor.rs index 054d28320a2a5..5eaaef46c4921 100644 --- a/aptos-move/e2e-tests/src/executor.rs +++ b/aptos-move/e2e-tests/src/executor.rs @@ -766,7 +766,7 @@ impl FakeExecutor { .expect("Must execute transactions"); // Check if we emit the expected event for block metadata, there might be more events for transaction fees. - let event = outputs[0].events()[0] + let event = outputs[0].events()[1] .v1() .expect("The first event must be a block metadata v0 event") .clone(); diff --git a/aptos-move/framework/aptos-framework/doc/account.md b/aptos-move/framework/aptos-framework/doc/account.md index d17c58a984c9c..2244ba8a0e247 100644 --- a/aptos-move/framework/aptos-framework/doc/account.md +++ b/aptos-move/framework/aptos-framework/doc/account.md @@ -99,6 +99,7 @@ use 0x1::ed25519; use 0x1::error; use 0x1::event; +use 0x1::features; use 0x1::from_bcs; use 0x1::guid; use 0x1::hash; @@ -1264,11 +1265,17 @@ to rotate his address to Alice's address in the first place. if (from_scheme == ED25519_SCHEME) { let from_pk = ed25519::new_unvalidated_public_key_from_bytes(from_public_key_bytes); let from_auth_key = ed25519::unvalidated_public_key_to_authentication_key(&from_pk); - assert!(account_resource.authentication_key == from_auth_key, error::unauthenticated(EWRONG_CURRENT_PUBLIC_KEY)); + assert!( + account_resource.authentication_key == from_auth_key, + error::unauthenticated(EWRONG_CURRENT_PUBLIC_KEY) + ); } else if (from_scheme == MULTI_ED25519_SCHEME) { let from_pk = multi_ed25519::new_unvalidated_public_key_from_bytes(from_public_key_bytes); let from_auth_key = multi_ed25519::unvalidated_public_key_to_authentication_key(&from_pk); - assert!(account_resource.authentication_key == from_auth_key, error::unauthenticated(EWRONG_CURRENT_PUBLIC_KEY)); + assert!( + account_resource.authentication_key == from_auth_key, + error::unauthenticated(EWRONG_CURRENT_PUBLIC_KEY) + ); } else { abort error::invalid_argument(EINVALID_SCHEME) }; @@ -1283,8 +1290,18 @@ to rotate his address to Alice's address in the first place. }; // Assert the challenges signed by the current and new keys are valid - assert_valid_rotation_proof_signature_and_get_auth_key(from_scheme, from_public_key_bytes, cap_rotate_key, &challenge); - let new_auth_key = assert_valid_rotation_proof_signature_and_get_auth_key(to_scheme, to_public_key_bytes, cap_update_table, &challenge); + assert_valid_rotation_proof_signature_and_get_auth_key( + from_scheme, + from_public_key_bytes, + cap_rotate_key, + &challenge + ); + let new_auth_key = assert_valid_rotation_proof_signature_and_get_auth_key( + to_scheme, + to_public_key_bytes, + cap_update_table, + &challenge + ); // Update the `OriginatingAddress` table. update_auth_key_and_originating_address_table(addr, account_resource, new_auth_key); @@ -1322,7 +1339,10 @@ to rotate his address to Alice's address in the first place. // Check that there exists a rotation capability offer at the offerer's account resource for the delegate. let delegate_address = signer::address_of(delegate_signer); let offerer_account_resource = borrow_global<Account>(rotation_cap_offerer_address); - assert!(option::contains(&offerer_account_resource.rotation_capability_offer.for, &delegate_address), error::not_found(ENO_SUCH_ROTATION_CAPABILITY_OFFER)); + assert!( + option::contains(&offerer_account_resource.rotation_capability_offer.for, &delegate_address), + error::not_found(ENO_SUCH_ROTATION_CAPABILITY_OFFER) + ); let curr_auth_key = from_bcs::to_address(offerer_account_resource.authentication_key); let challenge = RotationProofChallenge { @@ -1333,11 +1353,20 @@ to rotate his address to Alice's address in the first place. }; // Verifies that the `RotationProofChallenge` from above is signed under the new public key that we are rotating to. l - let new_auth_key = assert_valid_rotation_proof_signature_and_get_auth_key(new_scheme, new_public_key_bytes, cap_update_table, &challenge); + let new_auth_key = assert_valid_rotation_proof_signature_and_get_auth_key( + new_scheme, + new_public_key_bytes, + cap_update_table, + &challenge + ); // Update the `OriginatingAddress` table, so we can find the originating address using the new address. let offerer_account_resource = borrow_global_mut<Account>(rotation_cap_offerer_address); - update_auth_key_and_originating_address_table(rotation_cap_offerer_address, offerer_account_resource, new_auth_key); + update_auth_key_and_originating_address_table( + rotation_cap_offerer_address, + offerer_account_resource, + new_auth_key + ); } @@ -1400,17 +1429,29 @@ offer, calling this function will replace the previous recipient_addressif (account_scheme == ED25519_SCHEME) { let pubkey = ed25519::new_unvalidated_public_key_from_bytes(account_public_key_bytes); let expected_auth_key = ed25519::unvalidated_public_key_to_authentication_key(&pubkey); - assert!(account_resource.authentication_key == expected_auth_key, error::invalid_argument(EWRONG_CURRENT_PUBLIC_KEY)); + assert!( + account_resource.authentication_key == expected_auth_key, + error::invalid_argument(EWRONG_CURRENT_PUBLIC_KEY) + ); let rotation_capability_sig = ed25519::new_signature_from_bytes(rotation_capability_sig_bytes); - assert!(ed25519::signature_verify_strict_t(&rotation_capability_sig, &pubkey, proof_challenge), error::invalid_argument(EINVALID_PROOF_OF_KNOWLEDGE)); + assert!( + ed25519::signature_verify_strict_t(&rotation_capability_sig, &pubkey, proof_challenge), + error::invalid_argument(EINVALID_PROOF_OF_KNOWLEDGE) + ); } else if (account_scheme == MULTI_ED25519_SCHEME) { let pubkey = multi_ed25519::new_unvalidated_public_key_from_bytes(account_public_key_bytes); let expected_auth_key = multi_ed25519::unvalidated_public_key_to_authentication_key(&pubkey); - assert!(account_resource.authentication_key == expected_auth_key, error::invalid_argument(EWRONG_CURRENT_PUBLIC_KEY)); + assert!( + account_resource.authentication_key == expected_auth_key, + error::invalid_argument(EWRONG_CURRENT_PUBLIC_KEY) + ); let rotation_capability_sig = multi_ed25519::new_signature_from_bytes(rotation_capability_sig_bytes); - assert!(multi_ed25519::signature_verify_strict_t(&rotation_capability_sig, &pubkey, proof_challenge), error::invalid_argument(EINVALID_PROOF_OF_KNOWLEDGE)); + assert!( + multi_ed25519::signature_verify_strict_t(&rotation_capability_sig, &pubkey, proof_challenge), + error::invalid_argument(EINVALID_PROOF_OF_KNOWLEDGE) + ); } else { abort error::invalid_argument(EINVALID_SCHEME) }; @@ -1502,7 +1543,10 @@ Revoke the rotation capability offer given to to_be_revoked_recipient_addr assert!(exists_at(to_be_revoked_address), error::not_found(EACCOUNT_DOES_NOT_EXIST)); let addr = signer::address_of(account); let account_resource = borrow_global_mut<Account>(addr); - assert!(option::contains(&account_resource.rotation_capability_offer.for, &to_be_revoked_address), error::not_found(ENO_SUCH_ROTATION_CAPABILITY_OFFER)); + assert!( + option::contains(&account_resource.rotation_capability_offer.for, &to_be_revoked_address), + error::not_found(ENO_SUCH_ROTATION_CAPABILITY_OFFER) + ); revoke_any_rotation_capability(account); } @@ -1669,7 +1713,10 @@ has a signer capability offer from accoun assert!(exists_at(to_be_revoked_address), error::not_found(EACCOUNT_DOES_NOT_EXIST)); let addr = signer::address_of(account); let account_resource = borrow_global_mut<Account>(addr); - assert!(option::contains(&account_resource.signer_capability_offer.for, &to_be_revoked_address), error::not_found(ENO_SUCH_SIGNER_CAPABILITY)); + assert!( + option::contains(&account_resource.signer_capability_offer.for, &to_be_revoked_address), + error::not_found(ENO_SUCH_SIGNER_CAPABILITY) + ); revoke_any_signer_capability(account); } @@ -1727,7 +1774,10 @@ at the offerer's address. // Check if there's an existing signer capability offer from the offerer. let account_resource = borrow_global<Account>(offerer_address); let addr = signer::address_of(account); - assert!(option::contains(&account_resource.signer_capability_offer.for, &addr), error::not_found(ENO_SUCH_SIGNER_CAPABILITY)); + assert!( + option::contains(&account_resource.signer_capability_offer.for, &addr), + error::not_found(ENO_SUCH_SIGNER_CAPABILITY) + ); create_signer(offerer_address) } @@ -1753,16 +1803,27 @@ Helper functions for authentication key rotation.

Implementation -
fun assert_valid_rotation_proof_signature_and_get_auth_key(scheme: u8, public_key_bytes: vector<u8>, signature: vector<u8>, challenge: &RotationProofChallenge): vector<u8> {
+
fun assert_valid_rotation_proof_signature_and_get_auth_key(
+    scheme: u8,
+    public_key_bytes: vector<u8>,
+    signature: vector<u8>,
+    challenge: &RotationProofChallenge
+): vector<u8> {
     if (scheme == ED25519_SCHEME) {
         let pk = ed25519::new_unvalidated_public_key_from_bytes(public_key_bytes);
         let sig = ed25519::new_signature_from_bytes(signature);
-        assert!(ed25519::signature_verify_strict_t(&sig, &pk, *challenge), std::error::invalid_argument(EINVALID_PROOF_OF_KNOWLEDGE));
+        assert!(
+            ed25519::signature_verify_strict_t(&sig, &pk, *challenge),
+            std::error::invalid_argument(EINVALID_PROOF_OF_KNOWLEDGE)
+        );
         ed25519::unvalidated_public_key_to_authentication_key(&pk)
     } else if (scheme == MULTI_ED25519_SCHEME) {
         let pk = multi_ed25519::new_unvalidated_public_key_from_bytes(public_key_bytes);
         let sig = multi_ed25519::new_signature_from_bytes(signature);
-        assert!(multi_ed25519::signature_verify_strict_t(&sig, &pk, *challenge), std::error::invalid_argument(EINVALID_PROOF_OF_KNOWLEDGE));
+        assert!(
+            multi_ed25519::signature_verify_strict_t(&sig, &pk, *challenge),
+            std::error::invalid_argument(EINVALID_PROOF_OF_KNOWLEDGE)
+        );
         multi_ed25519::unvalidated_public_key_to_authentication_key(&pk)
     } else {
         abort error::invalid_argument(EINVALID_SCHEME)
@@ -1812,18 +1873,23 @@ in the event of key recovery.
         // for interoperability because different dapps can implement this in different ways.
         // If the account with address b calls this function with two valid signatures, it will abort at this step,
         // because address b is not the account's originating address.
-        assert!(originating_addr == table::remove(address_map, curr_auth_key), error::not_found(EINVALID_ORIGINATING_ADDRESS));
+        assert!(
+            originating_addr == table::remove(address_map, curr_auth_key),
+            error::not_found(EINVALID_ORIGINATING_ADDRESS)
+        );
     };
 
     // Set `OriginatingAddress[new_auth_key] = originating_address`.
     let new_auth_key = from_bcs::to_address(new_auth_key_vector);
     table::add(address_map, new_auth_key, originating_addr);
 
-    event::emit<KeyRotation>(KeyRotation {
-        account: originating_addr,
-        old_authentication_key: account_resource.authentication_key,
-        new_authentication_key: new_auth_key_vector,
-    });
+    if (std::features::module_event_migration_enabled()) {
+        event::emit(KeyRotation {
+            account: originating_addr,
+            old_authentication_key: account_resource.authentication_key,
+            new_authentication_key: new_auth_key_vector,
+        });
+    };
     event::emit_event<KeyRotationEvent>(
         &mut account_resource.key_rotation_events,
         KeyRotationEvent {
diff --git a/aptos-move/framework/aptos-framework/doc/aptos_account.md b/aptos-move/framework/aptos-framework/doc/aptos_account.md
index 4dfe00fa0c476..014edcdaa2cb1 100644
--- a/aptos-move/framework/aptos-framework/doc/aptos_account.md
+++ b/aptos-move/framework/aptos-framework/doc/aptos_account.md
@@ -7,7 +7,7 @@
 
 -  [Resource `DirectTransferConfig`](#0x1_aptos_account_DirectTransferConfig)
 -  [Struct `DirectCoinTransferConfigUpdatedEvent`](#0x1_aptos_account_DirectCoinTransferConfigUpdatedEvent)
--  [Struct `AllowDirectTransfers`](#0x1_aptos_account_AllowDirectTransfers)
+-  [Struct `DirectCoinTransferConfigUpdated`](#0x1_aptos_account_DirectCoinTransferConfigUpdated)
 -  [Constants](#@Constants_0)
 -  [Function `create_account`](#0x1_aptos_account_create_account)
 -  [Function `batch_transfer`](#0x1_aptos_account_batch_transfer)
@@ -40,6 +40,7 @@
 use 0x1::create_signer;
 use 0x1::error;
 use 0x1::event;
+use 0x1::features;
 use 0x1::signer;
 
@@ -109,14 +110,14 @@ Event emitted when an account's direct coins transfer config is updated. - + -## Struct `AllowDirectTransfers` +## Struct `DirectCoinTransferConfigUpdated`
#[event]
-struct AllowDirectTransfers has drop, store
+struct DirectCoinTransferConfigUpdated has drop, store
 
@@ -469,8 +470,10 @@ Set whether account can receiv }; direct_transfer_config.allow_arbitrary_coin_transfers = allow; - emit( - AllowDirectTransfers { account: addr, new_allow_direct_transfers: allow }); + + if (std::features::module_event_migration_enabled()) { + emit(DirectCoinTransferConfigUpdated { account: addr, new_allow_direct_transfers: allow }); + }; emit_event( &mut direct_transfer_config.update_coin_transfer_events, DirectCoinTransferConfigUpdatedEvent { new_allow_direct_transfers: allow }); @@ -479,8 +482,9 @@ Set whether account can receiv allow_arbitrary_coin_transfers: allow, update_coin_transfer_events: new_event_handle<DirectCoinTransferConfigUpdatedEvent>(account), }; - emit( - AllowDirectTransfers { account: addr, new_allow_direct_transfers: allow }); + if (std::features::module_event_migration_enabled()) { + emit(DirectCoinTransferConfigUpdated { account: addr, new_allow_direct_transfers: allow }); + }; emit_event( &mut direct_transfer_config.update_coin_transfer_events, DirectCoinTransferConfigUpdatedEvent { new_allow_direct_transfers: allow }); diff --git a/aptos-move/framework/aptos-framework/doc/aptos_governance.md b/aptos-move/framework/aptos-framework/doc/aptos_governance.md index 333da08e8e989..744fbddd4215f 100644 --- a/aptos-move/framework/aptos-framework/doc/aptos_governance.md +++ b/aptos-move/framework/aptos-framework/doc/aptos_governance.md @@ -26,6 +26,9 @@ on a proposal multiple times as long as the total voting power of these votes do - [Struct `CreateProposalEvent`](#0x1_aptos_governance_CreateProposalEvent) - [Struct `VoteEvent`](#0x1_aptos_governance_VoteEvent) - [Struct `UpdateConfigEvent`](#0x1_aptos_governance_UpdateConfigEvent) +- [Struct `CreateProposal`](#0x1_aptos_governance_CreateProposal) +- [Struct `Vote`](#0x1_aptos_governance_Vote) +- [Struct `UpdateConfig`](#0x1_aptos_governance_UpdateConfig) - [Constants](#@Constants_0) - [Function `store_signer_cap`](#0x1_aptos_governance_store_signer_cap) - [Function `initialize`](#0x1_aptos_governance_initialize) @@ -461,6 +464,153 @@ Event emitted when the governance configs are updated. +
+Fields + + +
+
+min_voting_threshold: u128 +
+
+ +
+
+required_proposer_stake: u64 +
+
+ +
+
+voting_duration_secs: u64 +
+
+ +
+
+ + +
+ + + +## Struct `CreateProposal` + +Event emitted when a proposal is created. + + +
#[event]
+struct CreateProposal has drop, store
+
+ + + +
+Fields + + +
+
+proposer: address +
+
+ +
+
+stake_pool: address +
+
+ +
+
+proposal_id: u64 +
+
+ +
+
+execution_hash: vector<u8> +
+
+ +
+
+proposal_metadata: simple_map::SimpleMap<string::String, vector<u8>> +
+
+ +
+
+ + +
+ + + +## Struct `Vote` + +Event emitted when there's a vote on a proposa; + + +
#[event]
+struct Vote has drop, store
+
+ + + +
+Fields + + +
+
+proposal_id: u64 +
+
+ +
+
+voter: address +
+
+ +
+
+stake_pool: address +
+
+ +
+
+num_votes: u64 +
+
+ +
+
+should_pass: bool +
+
+ +
+
+ + +
+ + + +## Struct `UpdateConfig` + +Event emitted when the governance configs are updated. + + +
#[event]
+struct UpdateConfig has drop, store
+
+ + +
Fields @@ -688,7 +838,10 @@ Stores the signer capability for a given address. system_addresses::assert_framework_reserved(signer_address); if (!exists<GovernanceResponsbility>(@aptos_framework)) { - move_to(aptos_framework, GovernanceResponsbility { signer_caps: simple_map::create<address, SignerCapability>() }); + move_to( + aptos_framework, + GovernanceResponsbility { signer_caps: simple_map::create<address, SignerCapability>() } + ); }; let signer_caps = &mut borrow_global_mut<GovernanceResponsbility>(@aptos_framework).signer_caps; @@ -780,6 +933,15 @@ AptosGovernance. governance_config.min_voting_threshold = min_voting_threshold; governance_config.required_proposer_stake = required_proposer_stake; + if (std::features::module_event_migration_enabled()) { + event::emit( + UpdateConfig { + min_voting_threshold, + required_proposer_stake, + voting_duration_secs + }, + ) + }; let events = borrow_global_mut<GovernanceEvents>(@aptos_framework); event::emit_event<UpdateConfigEvent>( &mut events.update_config_events, @@ -954,10 +1116,16 @@ Note: a stake pool's voting power on a proposal could increase over time(e.g. re Implementation -
public fun get_remaining_voting_power(stake_pool: address, proposal_id: u64): u64 acquires VotingRecords, VotingRecordsV2 {
+
public fun get_remaining_voting_power(
+    stake_pool: address,
+    proposal_id: u64
+): u64 acquires VotingRecords, VotingRecordsV2 {
     assert_voting_initialization();
 
-    let proposal_expiration = voting::get_proposal_expiration_secs<GovernanceProposal>(@aptos_framework, proposal_id);
+    let proposal_expiration = voting::get_proposal_expiration_secs<GovernanceProposal>(
+        @aptos_framework,
+        proposal_id
+    );
     let lockup_until = stake::get_lockup_secs(stake_pool);
     // The voter's stake needs to be locked up at least as long as the proposal's expiration.
     // Also no one can vote on a expired proposal.
@@ -1046,7 +1214,14 @@ only the exact script with matching hash can be successfully executed.
     metadata_hash: vector<u8>,
     is_multi_step_proposal: bool,
 ) acquires GovernanceConfig, GovernanceEvents {
-    create_proposal_v2_impl(proposer, stake_pool, execution_hash, metadata_location, metadata_hash, is_multi_step_proposal);
+    create_proposal_v2_impl(
+        proposer,
+        stake_pool,
+        execution_hash,
+        metadata_location,
+        metadata_hash,
+        is_multi_step_proposal
+    );
 }
 
@@ -1082,7 +1257,10 @@ Return proposal_id when a proposal is successfully created. is_multi_step_proposal: bool, ): u64 acquires GovernanceConfig, GovernanceEvents { let proposer_address = signer::address_of(proposer); - assert!(stake::get_delegated_voter(stake_pool) == proposer_address, error::invalid_argument(ENOT_DELEGATED_VOTER)); + assert!( + stake::get_delegated_voter(stake_pool) == proposer_address, + error::invalid_argument(ENOT_DELEGATED_VOTER) + ); // The proposer's stake needs to be at least the required bond amount. let governance_config = borrow_global<GovernanceConfig>(@aptos_framework); @@ -1127,6 +1305,17 @@ Return proposal_id when a proposal is successfully created. is_multi_step_proposal, ); + if (std::features::module_event_migration_enabled()) { + event::emit( + CreateProposal { + proposal_id, + proposer: proposer_address, + stake_pool, + execution_hash, + proposal_metadata, + }, + ); + }; let events = borrow_global_mut<GovernanceEvents>(@aptos_framework); event::emit_event<CreateProposalEvent>( &mut events.create_proposal_events, @@ -1167,7 +1356,7 @@ Vote on proposal with proposal_id and all voting power from s stake_pool: address, proposal_id: u64, should_pass: bool, -) acquires ApprovedExecutionHashes, GovernanceEvents, VotingRecords, VotingRecordsV2 { +) acquires ApprovedExecutionHashes, VotingRecords, VotingRecordsV2, GovernanceEvents { vote_internal(voter, stake_pool, proposal_id, MAX_U64, should_pass); }
@@ -1198,7 +1387,7 @@ Vote on proposal with proposal_id and specified voting power from < proposal_id: u64, voting_power: u64, should_pass: bool, -) acquires ApprovedExecutionHashes, GovernanceEvents, VotingRecords, VotingRecordsV2 { +) acquires ApprovedExecutionHashes, VotingRecords, VotingRecordsV2, GovernanceEvents { vote_internal(voter, stake_pool, proposal_id, voting_power, should_pass); }
@@ -1232,12 +1421,15 @@ cannot vote on the proposal even after partial governance voting is enabled. proposal_id: u64, voting_power: u64, should_pass: bool, -) acquires ApprovedExecutionHashes, GovernanceEvents, VotingRecords, VotingRecordsV2 { +) acquires ApprovedExecutionHashes, VotingRecords, VotingRecordsV2, GovernanceEvents { let voter_address = signer::address_of(voter); assert!(stake::get_delegated_voter(stake_pool) == voter_address, error::invalid_argument(ENOT_DELEGATED_VOTER)); // The voter's stake needs to be locked up at least as long as the proposal's expiration. - let proposal_expiration = voting::get_proposal_expiration_secs<GovernanceProposal>(@aptos_framework, proposal_id); + let proposal_expiration = voting::get_proposal_expiration_secs<GovernanceProposal>( + @aptos_framework, + proposal_id + ); assert!( stake::get_lockup_secs(stake_pool) >= proposal_expiration, error::invalid_argument(EINSUFFICIENT_STAKE_LOCKUP), @@ -1246,7 +1438,7 @@ cannot vote on the proposal even after partial governance voting is enabled. // If a stake pool has already voted on a proposal before partial governance voting is enabled, // `get_remaining_voting_power` returns 0. let staking_pool_voting_power = get_remaining_voting_power(stake_pool, proposal_id); - voting_power= min(voting_power, staking_pool_voting_power); + voting_power = min(voting_power, staking_pool_voting_power); // Short-circuit if the voter has no voting power. assert!(voting_power > 0, error::invalid_argument(ENO_VOTING_POWER)); @@ -1276,6 +1468,17 @@ cannot vote on the proposal even after partial governance voting is enabled. table::add(&mut voting_records.votes, record_key, true); }; + if (std::features::module_event_migration_enabled()) { + event::emit( + Vote { + proposal_id, + voter: voter_address, + stake_pool, + num_votes: voting_power, + should_pass, + }, + ); + }; let events = borrow_global_mut<GovernanceEvents>(@aptos_framework); event::emit_event<VoteEvent>( &mut events.vote_events, @@ -1382,7 +1585,10 @@ than yes). Implementation -
public fun resolve(proposal_id: u64, signer_address: address): signer acquires ApprovedExecutionHashes, GovernanceResponsbility {
+
public fun resolve(
+    proposal_id: u64,
+    signer_address: address
+): signer acquires ApprovedExecutionHashes, GovernanceResponsbility {
     voting::resolve<GovernanceProposal>(@aptos_framework, proposal_id);
     remove_approved_hash(proposal_id);
     get_signer(signer_address)
@@ -1409,7 +1615,11 @@ Resolve a successful multi-step proposal. This would fail if the proposal is not
 Implementation
 
 
-
public fun resolve_multi_step_proposal(proposal_id: u64, signer_address: address, next_execution_hash: vector<u8>): signer acquires GovernanceResponsbility, ApprovedExecutionHashes {
+
public fun resolve_multi_step_proposal(
+    proposal_id: u64,
+    signer_address: address,
+    next_execution_hash: vector<u8>
+): signer acquires GovernanceResponsbility, ApprovedExecutionHashes {
     voting::resolve_proposal_v2<GovernanceProposal>(@aptos_framework, proposal_id, next_execution_hash);
     // If the current step is the last step of this multi-step proposal,
     // we will remove the execution hash from the ApprovedExecutionHashes map.
@@ -1692,7 +1902,10 @@ Return a signer for making changes to 0x1 as part of on-chain governance proposa
 Implementation
 
 
-
fun create_proposal_metadata(metadata_location: vector<u8>, metadata_hash: vector<u8>): SimpleMap<String, vector<u8>> {
+
fun create_proposal_metadata(
+    metadata_location: vector<u8>,
+    metadata_hash: vector<u8>
+): SimpleMap<String, vector<u8>> {
     assert!(string::length(&utf8(metadata_location)) <= 256, error::invalid_argument(EMETADATA_LOCATION_TOO_LONG));
     assert!(string::length(&utf8(metadata_hash)) <= 256, error::invalid_argument(EMETADATA_HASH_TOO_LONG));
 
@@ -2198,80 +2411,6 @@ The same as spec of 
-
-
-
schema CreateProposalAbortsIf {
-    proposer: &signer;
-    stake_pool: address;
-    execution_hash: vector<u8>;
-    metadata_location: vector<u8>;
-    metadata_hash: vector<u8>;
-    include VotingGetDelegatedVoterAbortsIf { sign: proposer };
-    include AbortsIfNotGovernanceConfig;
-    include GetVotingPowerAbortsIf { pool_address: stake_pool };
-    let staking_config = global<staking_config::StakingConfig>(@aptos_framework);
-    let allow_validator_set_change = staking_config.allow_validator_set_change;
-    let stake_pool_res = global<stake::StakePool>(stake_pool);
-    let stake_balance_0 = stake_pool_res.active.value + stake_pool_res.pending_active.value + stake_pool_res.pending_inactive.value;
-    let stake_balance_1 = stake_pool_res.active.value + stake_pool_res.pending_inactive.value;
-    let stake_balance_2 = 0;
-    let governance_config = global<GovernanceConfig>(@aptos_framework);
-    let required_proposer_stake = governance_config.required_proposer_stake;
-    // This enforces high-level requirement 2:
-    aborts_if allow_validator_set_change && stake_balance_0 < required_proposer_stake;
-    aborts_if !allow_validator_set_change && stake::spec_is_current_epoch_validator(stake_pool) && stake_balance_1 < required_proposer_stake;
-    aborts_if !allow_validator_set_change && !stake::spec_is_current_epoch_validator(stake_pool) && stake_balance_2 < required_proposer_stake;
-    aborts_if !exists<timestamp::CurrentTimeMicroseconds>(@aptos_framework);
-    let current_time = timestamp::spec_now_seconds();
-    let proposal_expiration = current_time + governance_config.voting_duration_secs;
-    aborts_if stake_pool_res.locked_until_secs < proposal_expiration;
-    include CreateProposalMetadataAbortsIf;
-    let addr = aptos_std::type_info::type_of<AptosCoin>().account_address;
-    aborts_if !exists<coin::CoinInfo<AptosCoin>>(addr);
-    let maybe_supply = global<coin::CoinInfo<AptosCoin>>(addr).supply;
-    let supply = option::spec_borrow(maybe_supply);
-    let total_supply = aptos_framework::optional_aggregator::optional_aggregator_value(supply);
-    let early_resolution_vote_threshold_value = total_supply / 2 + 1;
-    aborts_if option::spec_is_some(maybe_supply) && governance_config.min_voting_threshold > early_resolution_vote_threshold_value;
-    aborts_if len(execution_hash) == 0;
-    aborts_if !exists<voting::VotingForum<GovernanceProposal>>(@aptos_framework);
-    let voting_forum = global<voting::VotingForum<GovernanceProposal>>(@aptos_framework);
-    let proposal_id = voting_forum.next_proposal_id;
-    aborts_if proposal_id + 1 > MAX_U64;
-    let post post_voting_forum = global<voting::VotingForum<GovernanceProposal>>(@aptos_framework);
-    let post post_next_proposal_id = post_voting_forum.next_proposal_id;
-    ensures post_next_proposal_id == proposal_id + 1;
-    aborts_if !string::spec_internal_check_utf8(voting::IS_MULTI_STEP_PROPOSAL_KEY);
-    aborts_if !string::spec_internal_check_utf8(voting::IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY);
-    aborts_if table::spec_contains(voting_forum.proposals,proposal_id);
-    ensures table::spec_contains(post_voting_forum.proposals, proposal_id);
-    aborts_if !exists<GovernanceEvents>(@aptos_framework);
-}
-
- - - - - - - -
schema VotingGetDelegatedVoterAbortsIf {
-    stake_pool: address;
-    sign: signer;
-    let addr = signer::address_of(sign);
-    let stake_pool_res = global<stake::StakePool>(stake_pool);
-    aborts_if !exists<stake::StakePool>(stake_pool);
-    aborts_if stake_pool_res.delegated_voter != addr;
-}
-
- - diff --git a/aptos-move/framework/aptos-framework/doc/block.md b/aptos-move/framework/aptos-framework/doc/block.md index 6e25b59ea1d9c..f5c4430007732 100644 --- a/aptos-move/framework/aptos-framework/doc/block.md +++ b/aptos-move/framework/aptos-framework/doc/block.md @@ -10,6 +10,8 @@ This module defines a struct storing the metadata of the block and new block eve - [Resource `CommitHistory`](#0x1_block_CommitHistory) - [Struct `NewBlockEvent`](#0x1_block_NewBlockEvent) - [Struct `UpdateEpochIntervalEvent`](#0x1_block_UpdateEpochIntervalEvent) +- [Struct `NewBlock`](#0x1_block_NewBlock) +- [Struct `UpdateEpochInterval`](#0x1_block_UpdateEpochInterval) - [Constants](#@Constants_0) - [Function `initialize`](#0x1_block_initialize) - [Function `initialize_commit_history`](#0x1_block_initialize_commit_history) @@ -225,6 +227,112 @@ Event emitted when a proposal is created. +
+Fields + + +
+
+old_epoch_interval: u64 +
+
+ +
+
+new_epoch_interval: u64 +
+
+ +
+
+ + +
+ + + +## Struct `NewBlock` + +Should be in-sync with NewBlockEvent rust struct in new_block.rs + + +
#[event]
+struct NewBlock has drop, store
+
+ + + +
+Fields + + +
+
+hash: address +
+
+ +
+
+epoch: u64 +
+
+ +
+
+round: u64 +
+
+ +
+
+height: u64 +
+
+ +
+
+previous_block_votes_bitvec: vector<u8> +
+
+ +
+
+proposer: address +
+
+ +
+
+failed_proposer_indices: vector<u64> +
+
+ +
+
+time_microseconds: u64 +
+
+ On-chain time during the block at the given height +
+
+ + +
+ + + +## Struct `UpdateEpochInterval` + +Event emitted when a proposal is created. + + +
#[event]
+struct UpdateEpochInterval has drop, store
+
+ + +
Fields @@ -401,6 +509,11 @@ Can only be called as part of the Aptos governance proposal process established let old_epoch_interval = block_resource.epoch_interval; block_resource.epoch_interval = new_epoch_interval; + if (std::features::module_event_migration_enabled()) { + event::emit( + UpdateEpochInterval { old_epoch_interval, new_epoch_interval }, + ); + }; event::emit_event<UpdateEpochIntervalEvent>( &mut block_resource.update_epoch_interval_events, UpdateEpochIntervalEvent { old_epoch_interval, new_epoch_interval }, @@ -480,6 +593,7 @@ Return epoch interval in seconds. let block_metadata_ref = borrow_global_mut<BlockResource>(@aptos_framework); block_metadata_ref.height = event::counter(&block_metadata_ref.new_block_events); + // Emit both event v1 and v2 for compatibility. Eventually only module events will be kept. let new_block_event = NewBlockEvent { hash, epoch, @@ -490,7 +604,17 @@ Return epoch interval in seconds. failed_proposer_indices, time_microseconds: timestamp, }; - emit_new_block_event(vm, &mut block_metadata_ref.new_block_events, new_block_event); + let new_block_event_v2 = NewBlock { + hash, + epoch, + round, + height: block_metadata_ref.height, + previous_block_votes_bitvec, + proposer, + failed_proposer_indices, + time_microseconds: timestamp, + }; + emit_new_block_event(vm, &mut block_metadata_ref.new_block_events, new_block_event, new_block_event_v2); if (features::collect_and_distribute_gas_fees()) { // Assign the fees collected from the previous block to the previous block proposer. @@ -635,7 +759,7 @@ Get the current block height Emit the event and update height and global timestamp -
fun emit_new_block_event(vm: &signer, event_handle: &mut event::EventHandle<block::NewBlockEvent>, new_block_event: block::NewBlockEvent)
+
fun emit_new_block_event(vm: &signer, event_handle: &mut event::EventHandle<block::NewBlockEvent>, new_block_event: block::NewBlockEvent, new_block_event_v2: block::NewBlock)
 
@@ -644,7 +768,12 @@ Emit the event and update height and global timestamp Implementation -
fun emit_new_block_event(vm: &signer, event_handle: &mut EventHandle<NewBlockEvent>, new_block_event: NewBlockEvent) acquires CommitHistory {
+
fun emit_new_block_event(
+    vm: &signer,
+    event_handle: &mut EventHandle<NewBlockEvent>,
+    new_block_event: NewBlockEvent,
+    new_block_event_v2: NewBlock
+) acquires CommitHistory {
     if (exists<CommitHistory>(@aptos_framework)) {
         let commit_history_ref = borrow_global_mut<CommitHistory>(@aptos_framework);
         let idx = commit_history_ref.next_idx;
@@ -662,6 +791,9 @@ Emit the event and update height and global timestamp
         event::counter(event_handle) == new_block_event.height,
         error::invalid_argument(ENUM_NEW_BLOCK_EVENTS_DOES_NOT_MATCH_BLOCK_HEIGHT),
     );
+    if (std::features::module_event_migration_enabled()) {
+        event::emit(new_block_event_v2);
+    };
     event::emit_event<NewBlockEvent>(event_handle, new_block_event);
 }
 
@@ -702,6 +834,16 @@ reconfiguration event. proposer: @vm_reserved, failed_proposer_indices: vector::empty(), time_microseconds: 0, + }, + NewBlock { + hash: genesis_id, + epoch: 0, + round: 0, + height: 0, + previous_block_votes_bitvec: vector::empty(), + proposer: @vm_reserved, + failed_proposer_indices: vector::empty(), + time_microseconds: 0, } ); } @@ -745,6 +887,16 @@ new block event for WriteSetPayload. proposer: @vm_reserved, failed_proposer_indices: vector::empty(), time_microseconds: timestamp::now_microseconds(), + }, + NewBlock { + hash: fake_block_hash, + epoch: reconfiguration::current_epoch(), + round: MAX_U64, + height: block_metadata_ref.height, + previous_block_votes_bitvec: vector::empty(), + proposer: @vm_reserved, + failed_proposer_indices: vector::empty(), + time_microseconds: timestamp::now_microseconds(), } ); } @@ -936,70 +1088,6 @@ The number of new events created does not exceed MAX_U64. - - - - -
schema BlockRequirement {
-    vm: signer;
-    hash: address;
-    epoch: u64;
-    round: u64;
-    proposer: address;
-    failed_proposer_indices: vector<u64>;
-    previous_block_votes_bitvec: vector<u8>;
-    timestamp: u64;
-    requires chain_status::is_operating();
-    requires system_addresses::is_vm(vm);
-    // This enforces high-level requirement 4:
-    requires proposer == @vm_reserved || stake::spec_is_current_epoch_validator(proposer);
-    requires (proposer == @vm_reserved) ==> (timestamp::spec_now_microseconds() == timestamp);
-    requires (proposer != @vm_reserved) ==> (timestamp::spec_now_microseconds() < timestamp);
-    requires exists<stake::ValidatorFees>(@aptos_framework);
-    requires exists<CoinInfo<AptosCoin>>(@aptos_framework);
-    include transaction_fee::RequiresCollectedFeesPerValueLeqBlockAptosSupply;
-    include staking_config::StakingRewardsConfigRequirement;
-}
-
- - - - - - - -
schema Initialize {
-    aptos_framework: signer;
-    epoch_interval_microsecs: u64;
-    let addr = signer::address_of(aptos_framework);
-    // This enforces high-level requirement 2:
-    aborts_if addr != @aptos_framework;
-    aborts_if epoch_interval_microsecs == 0;
-    aborts_if exists<BlockResource>(addr);
-    aborts_if exists<CommitHistory>(addr);
-    ensures exists<BlockResource>(addr);
-    ensures exists<CommitHistory>(addr);
-    ensures global<BlockResource>(addr).height == 0;
-}
-
- - - - - - - -
schema NewEventHandle {
-    aptos_framework: signer;
-    let addr = signer::address_of(aptos_framework);
-    let account = global<account::Account>(addr);
-    aborts_if !exists<account::Account>(addr);
-    aborts_if account.guid_creation_num + 2 > MAX_U64;
-}
-
- - - ### Function `update_epoch_interval_microsecs` @@ -1136,7 +1224,7 @@ The BlockResource existed under the @aptos_framework. ### Function `emit_new_block_event` -
fun emit_new_block_event(vm: &signer, event_handle: &mut event::EventHandle<block::NewBlockEvent>, new_block_event: block::NewBlockEvent)
+
fun emit_new_block_event(vm: &signer, event_handle: &mut event::EventHandle<block::NewBlockEvent>, new_block_event: block::NewBlockEvent, new_block_event_v2: block::NewBlock)
 
diff --git a/aptos-move/framework/aptos-framework/doc/coin.md b/aptos-move/framework/aptos-framework/doc/coin.md index ba2b7fd254cd0..374f28c66f76e 100644 --- a/aptos-move/framework/aptos-framework/doc/coin.md +++ b/aptos-move/framework/aptos-framework/doc/coin.md @@ -104,6 +104,7 @@ This module provides the foundation for typesafe Coins. use 0x1::aggregator_factory; use 0x1::error; use 0x1::event; +use 0x1::features; use 0x1::option; use 0x1::optional_aggregator; use 0x1::signer; @@ -1313,11 +1314,13 @@ Deposit the coin balance into the recipient's account and emit an event. !coin_store.frozen, error::permission_denied(EFROZEN), ); + if (std::features::module_event_migration_enabled()) { + event::emit(Deposit<CoinType> { account: account_addr, amount: coin.value }); + }; event::emit_event<DepositEvent>( &mut coin_store.deposit_events, DepositEvent { amount: coin.value }, ); - event::emit(Deposit<CoinType> { account: account_addr, amount: coin.value }); merge(&mut coin_store.coin, coin); } @@ -1902,11 +1905,13 @@ Withdraw specified amount of coin CoinType from the si error::permission_denied(EFROZEN), ); + if (std::features::module_event_migration_enabled()) { + event::emit(Withdraw<CoinType> { account: account_addr, amount }); + }; event::emit_event<WithdrawEvent>( &mut coin_store.withdraw_events, WithdrawEvent { amount }, ); - event::emit(Withdraw<CoinType> { account: account_addr, amount }); extract(&mut coin_store.coin, amount) } diff --git a/aptos-move/framework/aptos-framework/doc/fungible_asset.md b/aptos-move/framework/aptos-framework/doc/fungible_asset.md index 4a4b54fba8a79..e172870a4f759 100644 --- a/aptos-move/framework/aptos-framework/doc/fungible_asset.md +++ b/aptos-move/framework/aptos-framework/doc/fungible_asset.md @@ -1987,7 +1987,7 @@ Destroy an empty fungible asset. let store = borrow_global_mut<FungibleStore>(store_addr); store.balance = store.balance + amount; - event::emit<Deposit>(Deposit { store: store_addr, amount }); + event::emit(Deposit { store: store_addr, amount }); }
@@ -2021,7 +2021,7 @@ Extract amount of the fungible asset from store. store.balance = store.balance - amount; let metadata = store.metadata; - event::emit<Withdraw>(Withdraw { store: store_addr, amount }); + event::emit(Withdraw { store: store_addr, amount }); FungibleAsset { metadata, amount } } diff --git a/aptos-move/framework/aptos-framework/doc/multisig_account.md b/aptos-move/framework/aptos-framework/doc/multisig_account.md index 5a0a588ef6b0b..7e596b9f3e63f 100644 --- a/aptos-move/framework/aptos-framework/doc/multisig_account.md +++ b/aptos-move/framework/aptos-framework/doc/multisig_account.md @@ -48,14 +48,23 @@ and implement the governance voting logic on top. - [Struct `MultisigAccountCreationMessage`](#0x1_multisig_account_MultisigAccountCreationMessage) - [Struct `MultisigAccountCreationWithAuthKeyRevocationMessage`](#0x1_multisig_account_MultisigAccountCreationWithAuthKeyRevocationMessage) - [Struct `AddOwnersEvent`](#0x1_multisig_account_AddOwnersEvent) +- [Struct `AddOwners`](#0x1_multisig_account_AddOwners) - [Struct `RemoveOwnersEvent`](#0x1_multisig_account_RemoveOwnersEvent) +- [Struct `RemoveOwners`](#0x1_multisig_account_RemoveOwners) - [Struct `UpdateSignaturesRequiredEvent`](#0x1_multisig_account_UpdateSignaturesRequiredEvent) +- [Struct `UpdateSignaturesRequired`](#0x1_multisig_account_UpdateSignaturesRequired) - [Struct `CreateTransactionEvent`](#0x1_multisig_account_CreateTransactionEvent) +- [Struct `CreateTransaction`](#0x1_multisig_account_CreateTransaction) - [Struct `VoteEvent`](#0x1_multisig_account_VoteEvent) +- [Struct `Vote`](#0x1_multisig_account_Vote) - [Struct `ExecuteRejectedTransactionEvent`](#0x1_multisig_account_ExecuteRejectedTransactionEvent) +- [Struct `ExecuteRejectedTransaction`](#0x1_multisig_account_ExecuteRejectedTransaction) - [Struct `TransactionExecutionSucceededEvent`](#0x1_multisig_account_TransactionExecutionSucceededEvent) +- [Struct `TransactionExecutionSucceeded`](#0x1_multisig_account_TransactionExecutionSucceeded) - [Struct `TransactionExecutionFailedEvent`](#0x1_multisig_account_TransactionExecutionFailedEvent) +- [Struct `TransactionExecutionFailed`](#0x1_multisig_account_TransactionExecutionFailed) - [Struct `MetadataUpdatedEvent`](#0x1_multisig_account_MetadataUpdatedEvent) +- [Struct `MetadataUpdated`](#0x1_multisig_account_MetadataUpdated) - [Constants](#@Constants_0) - [Function `metadata`](#0x1_multisig_account_metadata) - [Function `num_signatures_required`](#0x1_multisig_account_num_signatures_required) @@ -495,6 +504,40 @@ Event emitted when new owners are added to the multisig account. +
+ + + +## Struct `AddOwners` + + + +
#[event]
+struct AddOwners has drop, store
+
+ + + +
+Fields + + +
+
+multisig_account: address +
+
+ +
+
+owners_added: vector<address> +
+
+ +
+
+ +
@@ -523,6 +566,40 @@ Event emitted when new owners are removed from the multisig account. + + + + +## Struct `RemoveOwners` + + + +
#[event]
+struct RemoveOwners has drop, store
+
+ + + +
+Fields + + +
+
+multisig_account: address +
+
+ +
+
+owners_removed: vector<address> +
+
+ +
+
+ +
@@ -557,6 +634,46 @@ Event emitted when the number of signatures required is updated. + + + + +## Struct `UpdateSignaturesRequired` + + + +
#[event]
+struct UpdateSignaturesRequired has drop, store
+
+ + + +
+Fields + + +
+
+multisig_account: address +
+
+ +
+
+old_num_signatures_required: u64 +
+
+ +
+
+new_num_signatures_required: u64 +
+
+ +
+
+ +
@@ -597,6 +714,52 @@ Event emitted when a transaction is created. + + + + +## Struct `CreateTransaction` + + + +
#[event]
+struct CreateTransaction has drop, store
+
+ + + +
+Fields + + +
+
+multisig_account: address +
+
+ +
+
+creator: address +
+
+ +
+
+sequence_number: u64 +
+
+ +
+
+transaction: multisig_account::MultisigTransaction +
+
+ +
+
+ +
@@ -637,6 +800,52 @@ Event emitted when an owner approves or rejects a transaction. + + + + +## Struct `Vote` + + + +
#[event]
+struct Vote has drop, store
+
+ + + +
+Fields + + +
+
+multisig_account: address +
+
+ +
+
+owner: address +
+
+ +
+
+sequence_number: u64 +
+
+ +
+
+approved: bool +
+
+ +
+
+ +
@@ -678,6 +887,52 @@ number of signatures required. + + + + +## Struct `ExecuteRejectedTransaction` + + + +
#[event]
+struct ExecuteRejectedTransaction has drop, store
+
+ + + +
+Fields + + +
+
+multisig_account: address +
+
+ +
+
+sequence_number: u64 +
+
+ +
+
+num_rejections: u64 +
+
+ +
+
+executor: address +
+
+ +
+
+ +
@@ -724,6 +979,58 @@ Event emitted when a transaction is executed. + + + + +## Struct `TransactionExecutionSucceeded` + + + +
#[event]
+struct TransactionExecutionSucceeded has drop, store
+
+ + + +
+Fields + + +
+
+multisig_account: address +
+
+ +
+
+executor: address +
+
+ +
+
+sequence_number: u64 +
+
+ +
+
+transaction_payload: vector<u8> +
+
+ +
+
+num_approvals: u64 +
+
+ +
+
+ +
@@ -776,6 +1083,64 @@ Event emitted when a transaction's execution failed. + + + + +## Struct `TransactionExecutionFailed` + + + +
#[event]
+struct TransactionExecutionFailed has drop, store
+
+ + + +
+Fields + + +
+
+multisig_account: address +
+
+ +
+
+executor: address +
+
+ +
+
+sequence_number: u64 +
+
+ +
+
+transaction_payload: vector<u8> +
+
+ +
+
+num_approvals: u64 +
+
+ +
+
+execution_error: multisig_account::ExecutionError +
+
+ +
+
+ +
@@ -810,6 +1175,46 @@ Event emitted when a transaction's metadata is updated. + + + + +## Struct `MetadataUpdated` + + + +
#[event]
+struct MetadataUpdated has drop, store
+
+ + + +
+Fields + + +
+
+multisig_account: address +
+
+ +
+
+old_metadata: simple_map::SimpleMap<string::String, vector<u8>> +
+
+ +
+
+new_metadata: simple_map::SimpleMap<string::String, vector<u8>> +
+
+ +
+
+ +
@@ -1193,7 +1598,9 @@ Return all pending transactions. Implementation -
public fun get_pending_transactions(multisig_account: address): vector<MultisigTransaction> acquires MultisigAccount {
+
public fun get_pending_transactions(
+    multisig_account: address
+): vector<MultisigTransaction> acquires MultisigAccount {
     let pending_transactions: vector<MultisigTransaction> = vector[];
     let multisig_account = borrow_global<MultisigAccount>(multisig_account);
     let i = multisig_account.last_executed_sequence_number + 1;
@@ -2222,6 +2629,15 @@ maliciously alter the number of signatures required.
     };
 
     if (emit_event) {
+        if (std::features::module_event_migration_enabled()) {
+            emit(
+                MetadataUpdated {
+                    multisig_account: multisig_address,
+                    old_metadata,
+                    new_metadata: multisig_account_resource.metadata,
+                }
+            )
+        };
         emit_event(
             &mut multisig_account_resource.metadata_updated_events,
             MetadataUpdatedEvent {
@@ -2272,7 +2688,7 @@ Create a multisig transaction, which will have one approval initially (from the
         creator,
         creation_time_secs: now_seconds(),
     };
-    add_transaction(creator, multisig_account_resource, transaction);
+    add_transaction(creator, multisig_account, multisig_account_resource, transaction);
 }
 
@@ -2318,7 +2734,7 @@ to provide the full payload, which will be validated against the hash stored on- creator, creation_time_secs: now_seconds(), }; - add_transaction(creator, multisig_account_resource, transaction); + add_transaction(creator, multisig_account, multisig_account_resource, transaction); }
@@ -2416,6 +2832,16 @@ will continue to be an accessible entry point. simple_map::add(votes, owner_addr, approved); }; + if (std::features::module_event_migration_enabled()) { + emit( + Vote { + multisig_account, + owner: owner_addr, + sequence_number, + approved, + } + ); + }; emit_event( &mut multisig_account_resource.vote_events, VoteEvent { @@ -2527,6 +2953,16 @@ Remove the next transaction if it has sufficient owner rejections. error::invalid_state(ENOT_ENOUGH_REJECTIONS), ); + if (std::features::module_event_migration_enabled()) { + emit( + ExecuteRejectedTransaction { + multisig_account, + sequence_number, + num_rejections, + executor: address_of(owner), + } + ); + }; emit_event( &mut multisig_account_resource.execute_rejected_transaction_events, ExecuteRejectedTransactionEvent { @@ -2657,6 +3093,17 @@ This function is private so no other code can call this beside the VM itself as ) acquires MultisigAccount { let num_approvals = transaction_execution_cleanup_common(executor, multisig_account); let multisig_account_resource = borrow_global_mut<MultisigAccount>(multisig_account); + if (std::features::module_event_migration_enabled()) { + emit( + TransactionExecutionSucceeded { + multisig_account, + sequence_number: multisig_account_resource.last_executed_sequence_number, + transaction_payload, + num_approvals, + executor, + } + ); + }; emit_event( &mut multisig_account_resource.execute_transaction_events, TransactionExecutionSucceededEvent { @@ -2698,6 +3145,18 @@ This function is private so no other code can call this beside the VM itself as ) acquires MultisigAccount { let num_approvals = transaction_execution_cleanup_common(executor, multisig_account); let multisig_account_resource = borrow_global_mut<MultisigAccount>(multisig_account); + if (std::features::module_event_migration_enabled()) { + emit( + TransactionExecutionFailed { + multisig_account, + executor, + sequence_number: multisig_account_resource.last_executed_sequence_number, + transaction_payload, + num_approvals, + execution_error, + } + ); + }; emit_event( &mut multisig_account_resource.transaction_execution_failed_events, TransactionExecutionFailedEvent { @@ -2790,7 +3249,7 @@ This function is private so no other code can call this beside the VM itself as -
fun add_transaction(creator: address, multisig_account: &mut multisig_account::MultisigAccount, transaction: multisig_account::MultisigTransaction)
+
fun add_transaction(creator: address, multisig_account_address: address, multisig_account: &mut multisig_account::MultisigAccount, transaction: multisig_account::MultisigTransaction)
 
@@ -2799,7 +3258,12 @@ This function is private so no other code can call this beside the VM itself as Implementation -
fun add_transaction(creator: address, multisig_account: &mut MultisigAccount, transaction: MultisigTransaction) {
+
fun add_transaction(
+    creator: address,
+    multisig_account_address: address,
+    multisig_account: &mut MultisigAccount,
+    transaction: MultisigTransaction
+) {
     if(features::multisig_v2_enhancement_feature_enabled()) {
         let num_pending_transactions = multisig_account.next_sequence_number - (multisig_account.last_executed_sequence_number + 1);
         assert!(
@@ -2814,6 +3278,11 @@ This function is private so no other code can call this beside the VM itself as
     let sequence_number = multisig_account.next_sequence_number;
     multisig_account.next_sequence_number = sequence_number + 1;
     table::add(&mut multisig_account.transactions, sequence_number, transaction);
+    if (std::features::module_event_migration_enabled()) {
+        emit(
+            CreateTransaction { multisig_account: multisig_account_address, creator, sequence_number, transaction }
+        );
+    };
     emit_event(
         &mut multisig_account.create_transaction_events,
         CreateTransactionEvent { creator, sequence_number, transaction },
@@ -3203,6 +3672,9 @@ Add new owners, remove owners to remove, update signatures required.
             &multisig_account_ref_mut.owners,
             multisig_address
         );
+        if (std::features::module_event_migration_enabled()) {
+            emit(AddOwners { multisig_account: multisig_address, owners_added: new_owners });
+        };
         emit_event(
             &mut multisig_account_ref_mut.add_owners_events,
             AddOwnersEvent { owners_added: new_owners }
@@ -3224,6 +3696,11 @@ Add new owners, remove owners to remove, update signatures required.
         });
         // Only emit event if owner(s) actually removed.
         if (vector::length(&owners_removed) > 0) {
+            if (std::features::module_event_migration_enabled()) {
+                emit(
+                    RemoveOwners { multisig_account: multisig_address, owners_removed }
+                );
+            };
             emit_event(
                 &mut multisig_account_ref_mut.remove_owners_events,
                 RemoveOwnersEvent { owners_removed }
@@ -3244,6 +3721,15 @@ Add new owners, remove owners to remove, update signatures required.
         if (new_num_signatures_required != old_num_signatures_required) {
             multisig_account_ref_mut.num_signatures_required =
                 new_num_signatures_required;
+            if (std::features::module_event_migration_enabled()) {
+                emit(
+                    UpdateSignaturesRequired {
+                        multisig_account: multisig_address,
+                        old_num_signatures_required,
+                        new_num_signatures_required,
+                    }
+                );
+            };
             emit_event(
                 &mut multisig_account_ref_mut.update_signature_required_events,
                 UpdateSignaturesRequiredEvent {
diff --git a/aptos-move/framework/aptos-framework/doc/object.md b/aptos-move/framework/aptos-framework/doc/object.md
index f6fedad987f5c..25fb646d306ab 100644
--- a/aptos-move/framework/aptos-framework/doc/object.md
+++ b/aptos-move/framework/aptos-framework/doc/object.md
@@ -32,6 +32,7 @@ make it so that a reference to a global object can be returned from a function.
 -  [Struct `LinearTransferRef`](#0x1_object_LinearTransferRef)
 -  [Struct `DeriveRef`](#0x1_object_DeriveRef)
 -  [Struct `TransferEvent`](#0x1_object_TransferEvent)
+-  [Struct `Transfer`](#0x1_object_Transfer)
 -  [Constants](#@Constants_0)
 -  [Function `is_burnt`](#0x1_object_is_burnt)
 -  [Function `address_to_object`](#0x1_object_address_to_object)
@@ -464,8 +465,48 @@ Used to create derived objects from a given objects.
 Emitted whenever the object's owner field is changed.
 
 
+
struct TransferEvent has drop, store
+
+ + + +
+Fields + + +
+
+object: address +
+
+ +
+
+from: address +
+
+ +
+
+to: address +
+
+ +
+
+ + +
+ + + +## Struct `Transfer` + +Emitted whenever the object's owner field is changed. + +
#[event]
-struct TransferEvent has drop, store
+struct Transfer has drop, store
 
@@ -1666,13 +1707,15 @@ Transfer to the destination address using a LinearTransferRef. object.owner == ref.owner, error::permission_denied(ENOT_OBJECT_OWNER), ); - event::emit( - TransferEvent { - object: ref.self, - from: object.owner, - to, - }, - ); + if (std::features::module_event_migration_enabled()) { + event::emit( + Transfer { + object: ref.self, + from: object.owner, + to, + }, + ); + }; event::emit_event( &mut object.transfer_events, TransferEvent { @@ -1801,7 +1844,7 @@ hierarchy. let object_core = borrow_global_mut<ObjectCore>(object); if (object_core.owner != to) { event::emit( - TransferEvent { + Transfer { object, from: object_core.owner, to, diff --git a/aptos-move/framework/aptos-framework/doc/reconfiguration.md b/aptos-move/framework/aptos-framework/doc/reconfiguration.md index 8bc6fe963b08b..e8bcf138c083a 100644 --- a/aptos-move/framework/aptos-framework/doc/reconfiguration.md +++ b/aptos-move/framework/aptos-framework/doc/reconfiguration.md @@ -8,6 +8,7 @@ to synchronize configuration changes for the validators. - [Struct `NewEpochEvent`](#0x1_reconfiguration_NewEpochEvent) +- [Struct `NewEpoch`](#0x1_reconfiguration_NewEpoch) - [Resource `Configuration`](#0x1_reconfiguration_Configuration) - [Resource `DisableReconfiguration`](#0x1_reconfiguration_DisableReconfiguration) - [Constants](#@Constants_0) @@ -57,7 +58,39 @@ with new configuration information. This is also called a "reconfiguration event" -
struct NewEpochEvent has drop, store
+
#[event]
+struct NewEpochEvent has drop, store
+
+ + + +
+Fields + + +
+
+epoch: u64 +
+
+ +
+
+ + +
+ + + +## Struct `NewEpoch` + +Event that signals consensus to start a new epoch, +with new configuration information. This is also called a +"reconfiguration event" + + +
#[event]
+struct NewEpoch has drop, store
 
@@ -395,6 +428,14 @@ Signal validators to start using new configuration. Must be called from friend c }, ); + if (std::features::module_event_migration_enabled()) { + event::emit( + NewEpoch { + epoch: config_ref.epoch, + }, + ); + }; + reconfiguration_state::on_reconfig_finish(); }
@@ -473,6 +514,13 @@ reconfiguration event. assert!(config_ref.epoch == 0 && config_ref.last_reconfiguration_time == 0, error::invalid_state(ECONFIGURATION)); config_ref.epoch = 1; + if (std::features::module_event_migration_enabled()) { + event::emit( + NewEpoch { + epoch: config_ref.epoch, + }, + ); + }; event::emit_event<NewEpochEvent>( &mut config_ref.events, NewEpochEvent { diff --git a/aptos-move/framework/aptos-framework/doc/stake.md b/aptos-move/framework/aptos-framework/doc/stake.md index 9771f7d823785..dd137c9db1e99 100644 --- a/aptos-move/framework/aptos-framework/doc/stake.md +++ b/aptos-move/framework/aptos-framework/doc/stake.md @@ -33,17 +33,29 @@ or if their stake drops below the min required, they would get removed at the en - [Struct `IndividualValidatorPerformance`](#0x1_stake_IndividualValidatorPerformance) - [Resource `ValidatorPerformance`](#0x1_stake_ValidatorPerformance) - [Struct `RegisterValidatorCandidateEvent`](#0x1_stake_RegisterValidatorCandidateEvent) +- [Struct `RegisterValidatorCandidate`](#0x1_stake_RegisterValidatorCandidate) - [Struct `SetOperatorEvent`](#0x1_stake_SetOperatorEvent) +- [Struct `SetOperator`](#0x1_stake_SetOperator) - [Struct `AddStakeEvent`](#0x1_stake_AddStakeEvent) +- [Struct `AddStake`](#0x1_stake_AddStake) - [Struct `ReactivateStakeEvent`](#0x1_stake_ReactivateStakeEvent) +- [Struct `ReactivateStake`](#0x1_stake_ReactivateStake) - [Struct `RotateConsensusKeyEvent`](#0x1_stake_RotateConsensusKeyEvent) +- [Struct `RotateConsensusKey`](#0x1_stake_RotateConsensusKey) - [Struct `UpdateNetworkAndFullnodeAddressesEvent`](#0x1_stake_UpdateNetworkAndFullnodeAddressesEvent) +- [Struct `UpdateNetworkAndFullnodeAddresses`](#0x1_stake_UpdateNetworkAndFullnodeAddresses) - [Struct `IncreaseLockupEvent`](#0x1_stake_IncreaseLockupEvent) +- [Struct `IncreaseLockup`](#0x1_stake_IncreaseLockup) - [Struct `JoinValidatorSetEvent`](#0x1_stake_JoinValidatorSetEvent) +- [Struct `JoinValidatorSet`](#0x1_stake_JoinValidatorSet) - [Struct `DistributeRewardsEvent`](#0x1_stake_DistributeRewardsEvent) +- [Struct `DistributeRewards`](#0x1_stake_DistributeRewards) - [Struct `UnlockStakeEvent`](#0x1_stake_UnlockStakeEvent) +- [Struct `UnlockStake`](#0x1_stake_UnlockStake) - [Struct `WithdrawStakeEvent`](#0x1_stake_WithdrawStakeEvent) +- [Struct `WithdrawStake`](#0x1_stake_WithdrawStake) - [Struct `LeaveValidatorSetEvent`](#0x1_stake_LeaveValidatorSetEvent) +- [Struct `LeaveValidatorSet`](#0x1_stake_LeaveValidatorSet) - [Resource `ValidatorFees`](#0x1_stake_ValidatorFees) - [Resource `AllowedValidators`](#0x1_stake_AllowedValidators) - [Resource `Ghost$ghost_valid_perf`](#0x1_stake_Ghost$ghost_valid_perf) @@ -602,6 +614,34 @@ This allows the Stake module to mint rewards to stakers. +
+Fields + + +
+
+pool_address: address +
+
+ +
+
+ + +
+ + + +## Struct `RegisterValidatorCandidate` + + + +
#[event]
+struct RegisterValidatorCandidate has drop, store
+
+ + +
Fields @@ -629,6 +669,46 @@ This allows the Stake module to mint rewards to stakers. +
+Fields + + +
+
+pool_address: address +
+
+ +
+
+old_operator: address +
+
+ +
+
+new_operator: address +
+
+ +
+
+ + +
+ + + +## Struct `SetOperator` + + + +
#[event]
+struct SetOperator has drop, store
+
+ + +
Fields @@ -668,6 +748,40 @@ This allows the Stake module to mint rewards to stakers. +
+Fields + + +
+
+pool_address: address +
+
+ +
+
+amount_added: u64 +
+
+ +
+
+ + +
+ + + +## Struct `AddStake` + + + +
#[event]
+struct AddStake has drop, store
+
+ + +
Fields @@ -701,6 +815,40 @@ This allows the Stake module to mint rewards to stakers. +
+Fields + + +
+
+pool_address: address +
+
+ +
+
+amount: u64 +
+
+ +
+
+ + +
+ + + +## Struct `ReactivateStake` + + + +
#[event]
+struct ReactivateStake has drop, store
+
+ + +
Fields @@ -734,6 +882,46 @@ This allows the Stake module to mint rewards to stakers. +
+Fields + + +
+
+pool_address: address +
+
+ +
+
+old_consensus_pubkey: vector<u8> +
+
+ +
+
+new_consensus_pubkey: vector<u8> +
+
+ +
+
+ + +
+ + + +## Struct `RotateConsensusKey` + + + +
#[event]
+struct RotateConsensusKey has drop, store
+
+ + +
Fields @@ -773,6 +961,58 @@ This allows the Stake module to mint rewards to stakers. +
+Fields + + +
+
+pool_address: address +
+
+ +
+
+old_network_addresses: vector<u8> +
+
+ +
+
+new_network_addresses: vector<u8> +
+
+ +
+
+old_fullnode_addresses: vector<u8> +
+
+ +
+
+new_fullnode_addresses: vector<u8> +
+
+ +
+
+ + +
+ + + +## Struct `UpdateNetworkAndFullnodeAddresses` + + + +
#[event]
+struct UpdateNetworkAndFullnodeAddresses has drop, store
+
+ + +
Fields @@ -824,6 +1064,46 @@ This allows the Stake module to mint rewards to stakers. +
+Fields + + +
+
+pool_address: address +
+
+ +
+
+old_locked_until_secs: u64 +
+
+ +
+
+new_locked_until_secs: u64 +
+
+ +
+
+ + +
+ + + +## Struct `IncreaseLockup` + + + +
#[event]
+struct IncreaseLockup has drop, store
+
+ + +
Fields @@ -863,6 +1143,34 @@ This allows the Stake module to mint rewards to stakers. +
+Fields + + +
+
+pool_address: address +
+
+ +
+
+ + +
+ + + +## Struct `JoinValidatorSet` + + + +
#[event]
+struct JoinValidatorSet has drop, store
+
+ + +
Fields @@ -890,6 +1198,40 @@ This allows the Stake module to mint rewards to stakers. +
+Fields + + +
+
+pool_address: address +
+
+ +
+
+rewards_amount: u64 +
+
+ +
+
+ + +
+ + + +## Struct `DistributeRewards` + + + +
#[event]
+struct DistributeRewards has drop, store
+
+ + +
Fields @@ -923,6 +1265,40 @@ This allows the Stake module to mint rewards to stakers. +
+Fields + + +
+
+pool_address: address +
+
+ +
+
+amount_unlocked: u64 +
+
+ +
+
+ + +
+ + + +## Struct `UnlockStake` + + + +
#[event]
+struct UnlockStake has drop, store
+
+ + +
Fields @@ -956,6 +1332,40 @@ This allows the Stake module to mint rewards to stakers. +
+Fields + + +
+
+pool_address: address +
+
+ +
+
+amount_withdrawn: u64 +
+
+ +
+
+ + +
+ + + +## Struct `WithdrawStake` + + + +
#[event]
+struct WithdrawStake has drop, store
+
+ + +
Fields @@ -989,6 +1399,34 @@ This allows the Stake module to mint rewards to stakers. +
+Fields + + +
+
+pool_address: address +
+
+ +
+
+ + +
+ + + +## Struct `LeaveValidatorSet` + + + +
#[event]
+struct LeaveValidatorSet has drop, store
+
+ + +
Fields @@ -1823,7 +2261,9 @@ Return the validator's config. Implementation -
public fun get_validator_config(pool_address: address): (vector<u8>, vector<u8>, vector<u8>) acquires ValidatorConfig {
+
public fun get_validator_config(
+    pool_address: address
+): (vector<u8>, vector<u8>, vector<u8>) acquires ValidatorConfig {
     assert_stake_pool_exists(pool_address);
     let validator_config = borrow_global<ValidatorConfig>(pool_address);
     (validator_config.consensus_pubkey, validator_config.network_addresses, validator_config.fullnode_addresses)
@@ -2115,7 +2555,9 @@ Initialize the validator account and give ownership to the signing account.
         add_stake_events: account::new_event_handle<AddStakeEvent>(owner),
         reactivate_stake_events: account::new_event_handle<ReactivateStakeEvent>(owner),
         rotate_consensus_key_events: account::new_event_handle<RotateConsensusKeyEvent>(owner),
-        update_network_and_fullnode_addresses_events: account::new_event_handle<UpdateNetworkAndFullnodeAddressesEvent>(owner),
+        update_network_and_fullnode_addresses_events: account::new_event_handle<UpdateNetworkAndFullnodeAddressesEvent>(
+            owner
+        ),
         increase_lockup_events: account::new_event_handle<IncreaseLockupEvent>(owner),
         join_validator_set_events: account::new_event_handle<JoinValidatorSetEvent>(owner),
         distribute_rewards_events: account::new_event_handle<DistributeRewardsEvent>(owner),
@@ -2262,6 +2704,16 @@ Allows an account with ownership capability to change the operator of the stake
     let old_operator = stake_pool.operator_address;
     stake_pool.operator_address = new_operator;
 
+    if (std::features::module_event_migration_enabled()) {
+        event::emit(
+            SetOperator {
+                pool_address,
+                old_operator,
+                new_operator,
+            },
+        );
+    };
+
     event::emit_event(
         &mut stake_pool.set_operator_events,
         SetOperatorEvent {
@@ -2411,6 +2863,14 @@ Add coins into pool_address. this requires the corresp
     let voting_power = get_next_epoch_voting_power(stake_pool);
     assert!(voting_power <= maximum_stake, error::invalid_argument(ESTAKE_EXCEEDS_MAX));
 
+    if (std::features::module_event_migration_enabled()) {
+        event::emit(
+            AddStake {
+                pool_address,
+                amount_added: amount,
+            },
+        );
+    };
     event::emit_event(
         &mut stake_pool.add_stake_events,
         AddStakeEvent {
@@ -2485,6 +2945,14 @@ Move amount of coins from pending_inactive to active.
     let reactivated_coins = coin::extract(&mut stake_pool.pending_inactive, amount);
     coin::merge(&mut stake_pool.active, reactivated_coins);
 
+    if (std::features::module_event_migration_enabled()) {
+        event::emit(
+            ReactivateStake {
+                pool_address,
+                amount,
+            },
+        );
+    };
     event::emit_event(
         &mut stake_pool.reactivate_stake_events,
         ReactivateStakeEvent {
@@ -2538,6 +3006,15 @@ Rotate the consensus key of the validator, it'll take effect in next epoch.
     assert!(option::is_some(pubkey_from_pop), error::invalid_argument(EINVALID_PUBLIC_KEY));
     validator_info.consensus_pubkey = new_consensus_pubkey;
 
+    if (std::features::module_event_migration_enabled()) {
+        event::emit(
+            RotateConsensusKey {
+                pool_address,
+                old_consensus_pubkey,
+                new_consensus_pubkey,
+            },
+        );
+    };
     event::emit_event(
         &mut stake_pool.rotate_consensus_key_events,
         RotateConsensusKeyEvent {
@@ -2586,6 +3063,17 @@ Update the network and full node addresses of the validator. This only takes eff
     let old_fullnode_addresses = validator_info.fullnode_addresses;
     validator_info.fullnode_addresses = new_fullnode_addresses;
 
+    if (std::features::module_event_migration_enabled()) {
+        event::emit(
+            UpdateNetworkAndFullnodeAddresses {
+                pool_address,
+                old_network_addresses,
+                new_network_addresses,
+                old_fullnode_addresses,
+                new_fullnode_addresses,
+            },
+        );
+    };
     event::emit_event(
         &mut stake_pool.update_network_and_fullnode_addresses_events,
         UpdateNetworkAndFullnodeAddressesEvent {
@@ -2596,6 +3084,7 @@ Update the network and full node addresses of the validator. This only takes eff
             new_fullnode_addresses,
         },
     );
+
 }
 
@@ -2659,6 +3148,15 @@ directly inactive if it's not from an active validator. assert!(old_locked_until_secs < new_locked_until_secs, error::invalid_argument(EINVALID_LOCKUP)); stake_pool.locked_until_secs = new_locked_until_secs; + if (std::features::module_event_migration_enabled()) { + event::emit( + IncreaseLockup { + pool_address, + old_locked_until_secs, + new_locked_until_secs, + }, + ); + }; event::emit_event( &mut stake_pool.increase_lockup_events, IncreaseLockupEvent { @@ -2756,10 +3254,18 @@ This internal version can only be called by the Genesis module during Genesis. // Validate the current validator set size has not exceeded the limit. let validator_set = borrow_global_mut<ValidatorSet>(@aptos_framework); - vector::push_back(&mut validator_set.pending_active, generate_validator_info(pool_address, stake_pool, *validator_config)); - let validator_set_size = vector::length(&validator_set.active_validators) + vector::length(&validator_set.pending_active); + vector::push_back( + &mut validator_set.pending_active, + generate_validator_info(pool_address, stake_pool, *validator_config) + ); + let validator_set_size = vector::length(&validator_set.active_validators) + vector::length( + &validator_set.pending_active + ); assert!(validator_set_size <= MAX_VALIDATOR_SET_SIZE, error::invalid_argument(EVALIDATOR_SET_TOO_LARGE)); + if (std::features::module_event_migration_enabled()) { + event::emit(JoinValidatorSet { pool_address }); + }; event::emit_event( &mut stake_pool.join_validator_set_events, JoinValidatorSetEvent { pool_address }, @@ -2833,6 +3339,14 @@ Unlock amount from the active stake. Only possible if the lockup ha let unlocked_stake = coin::extract(&mut stake_pool.active, amount); coin::merge<AptosCoin>(&mut stake_pool.pending_inactive, unlocked_stake); + if (std::features::module_event_migration_enabled()) { + event::emit( + UnlockStake { + pool_address, + amount_unlocked: amount, + }, + ); + }; event::emit_event( &mut stake_pool.unlock_stake_events, UnlockStakeEvent { @@ -2916,6 +3430,14 @@ Withdraw from pool_address's inactive stake with the corresponding withdraw_amount = min(withdraw_amount, coin::value(&stake_pool.inactive)); if (withdraw_amount == 0) return coin::zero<AptosCoin>(); + if (std::features::module_event_migration_enabled()) { + event::emit( + WithdrawStake { + pool_address, + amount_withdrawn: withdraw_amount, + }, + ); + }; event::emit_event( &mut stake_pool.withdraw_stake_events, WithdrawStakeEvent { @@ -2997,6 +3519,9 @@ Can only be called by the operator of the validator/staking pool. assert!(vector::length(&validator_set.active_validators) > 0, error::invalid_state(ELAST_VALIDATOR)); vector::push_back(&mut validator_set.pending_inactive, validator_info); + if (std::features::module_event_migration_enabled()) { + event::emit(LeaveValidatorSet { pool_address }); + }; event::emit_event( &mut stake_pool.leave_validator_set_events, LeaveValidatorSetEvent { @@ -3057,7 +3582,10 @@ This function cannot abort. Implementation -
public(friend) fun update_performance_statistics(proposer_index: Option<u64>, failed_proposer_indices: vector<u64>) acquires ValidatorPerformance {
+
public(friend) fun update_performance_statistics(
+    proposer_index: Option<u64>,
+    failed_proposer_indices: vector<u64>
+) acquires ValidatorPerformance {
     // Validator set cannot change until the end of the epoch, so the validator index in arguments should
     // match with those of the validators in ValidatorPerformance resource.
     let validator_perf = borrow_global_mut<ValidatorPerformance>(@aptos_framework);
@@ -3086,7 +3614,9 @@ This function cannot abort.
     while ({
         spec {
             invariant len(validator_perf.validators) == validator_len;
-            invariant (option::spec_is_some(ghost_proposer_idx) && option::spec_borrow(ghost_proposer_idx) < validator_len) ==>
+            invariant (option::spec_is_some(ghost_proposer_idx) && option::spec_borrow(
+                ghost_proposer_idx
+            ) < validator_len) ==>
                 (validator_perf.validators[option::spec_borrow(ghost_proposer_idx)].successful_proposals ==
                     ghost_valid_perf.validators[option::spec_borrow(ghost_proposer_idx)].successful_proposals + 1);
         };
@@ -3134,7 +3664,8 @@ power.
 Implementation
 
 
-
public(friend) fun on_new_epoch() acquires StakePool, AptosCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees {
+
public(friend) fun on_new_epoch(
+) acquires StakePool, AptosCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees {
     let validator_set = borrow_global_mut<ValidatorSet>(@aptos_framework);
     let config = staking_config::get();
     let validator_perf = borrow_global_mut<ValidatorPerformance>(@aptos_framework);
@@ -3598,6 +4129,9 @@ This function shouldn't abort.
         );
     };
 
+    if (std::features::module_event_migration_enabled()) {
+        event::emit(DistributeRewards { pool_address, rewards_amount });
+    };
     event::emit_event(
         &mut stake_pool.distribute_rewards_events,
         DistributeRewardsEvent {
@@ -3712,7 +4246,13 @@ Mint rewards corresponding to current epoch's acquires AptosCoinCapabilities {
     let stake_amount = coin::value(stake);
     let rewards_amount = if (stake_amount > 0) {
-        calculate_rewards_amount(stake_amount, num_successful_proposals, num_total_proposals, rewards_rate, rewards_rate_denominator)
+        calculate_rewards_amount(
+            stake_amount,
+            num_successful_proposals,
+            num_total_proposals,
+            rewards_rate,
+            rewards_rate_denominator
+        )
     } else {
         0
     };
@@ -3926,7 +4466,10 @@ Returns validator's next epoch voting power, including pending_active, active, a
 Implementation
 
 
-
public fun configure_allowed_validators(aptos_framework: &signer, accounts: vector<address>) acquires AllowedValidators {
+
public fun configure_allowed_validators(
+    aptos_framework: &signer,
+    accounts: vector<address>
+) acquires AllowedValidators {
     let aptos_framework_address = signer::address_of(aptos_framework);
     system_addresses::assert_aptos_framework(aptos_framework);
     if (!exists<AllowedValidators>(aptos_framework_address)) {
@@ -5150,76 +5693,6 @@ Returns validator's next epoch voting power, including pending_active, active, a
 
 
 
-
-
-
-
-
schema ResourceRequirement {
-    requires exists<AptosCoinCapabilities>(@aptos_framework);
-    requires exists<ValidatorPerformance>(@aptos_framework);
-    requires exists<ValidatorSet>(@aptos_framework);
-    requires exists<StakingConfig>(@aptos_framework);
-    requires exists<StakingRewardsConfig>(@aptos_framework) || !features::spec_periodical_reward_rate_decrease_enabled();
-    requires exists<timestamp::CurrentTimeMicroseconds>(@aptos_framework);
-    requires exists<ValidatorFees>(@aptos_framework);
-}
-
- - - - - - - -
fun spec_get_reward_rate_1(config: StakingConfig): num {
-   if (features::spec_periodical_reward_rate_decrease_enabled()) {
-       let epoch_rewards_rate = global<staking_config::StakingRewardsConfig>(@aptos_framework).rewards_rate;
-       if (epoch_rewards_rate.value == 0) {
-           0
-       } else {
-           let denominator_0 = aptos_std::fixed_point64::spec_divide_u128(staking_config::MAX_REWARDS_RATE, epoch_rewards_rate);
-           let denominator = if (denominator_0 > MAX_U64) {
-               MAX_U64
-           } else {
-               denominator_0
-           };
-           let nominator = aptos_std::fixed_point64::spec_multiply_u128(denominator, epoch_rewards_rate);
-           nominator
-       }
-   } else {
-           config.rewards_rate
-   }
-}
-
- - - - - - - -
fun spec_get_reward_rate_2(config: StakingConfig): num {
-   if (features::spec_periodical_reward_rate_decrease_enabled()) {
-       let epoch_rewards_rate = global<staking_config::StakingRewardsConfig>(@aptos_framework).rewards_rate;
-       if (epoch_rewards_rate.value == 0) {
-           1
-       } else {
-           let denominator_0 = aptos_std::fixed_point64::spec_divide_u128(staking_config::MAX_REWARDS_RATE, epoch_rewards_rate);
-           let denominator = if (denominator_0 > MAX_U64) {
-               MAX_U64
-           } else {
-               denominator_0
-           };
-           denominator
-       }
-   } else {
-           config.rewards_rate_denominator
-   }
-}
-
- - - ### Function `update_stake_pool` diff --git a/aptos-move/framework/aptos-framework/doc/staking_contract.md b/aptos-move/framework/aptos-framework/doc/staking_contract.md index 5c1dc6531b84e..9e979016b5071 100644 --- a/aptos-move/framework/aptos-framework/doc/staking_contract.md +++ b/aptos-move/framework/aptos-framework/doc/staking_contract.md @@ -36,7 +36,18 @@ pool. - [Resource `Store`](#0x1_staking_contract_Store) - [Resource `BeneficiaryForOperator`](#0x1_staking_contract_BeneficiaryForOperator) - [Struct `UpdateCommissionEvent`](#0x1_staking_contract_UpdateCommissionEvent) +- [Struct `UpdateCommission`](#0x1_staking_contract_UpdateCommission) - [Resource `StakingGroupUpdateCommissionEvent`](#0x1_staking_contract_StakingGroupUpdateCommissionEvent) +- [Struct `CreateStakingContract`](#0x1_staking_contract_CreateStakingContract) +- [Struct `UpdateVoter`](#0x1_staking_contract_UpdateVoter) +- [Struct `ResetLockup`](#0x1_staking_contract_ResetLockup) +- [Struct `AddStake`](#0x1_staking_contract_AddStake) +- [Struct `RequestCommission`](#0x1_staking_contract_RequestCommission) +- [Struct `UnlockStake`](#0x1_staking_contract_UnlockStake) +- [Struct `SwitchOperator`](#0x1_staking_contract_SwitchOperator) +- [Struct `AddDistribution`](#0x1_staking_contract_AddDistribution) +- [Struct `Distribute`](#0x1_staking_contract_Distribute) +- [Struct `SetBeneficiaryForOperator`](#0x1_staking_contract_SetBeneficiaryForOperator) - [Struct `CreateStakingContractEvent`](#0x1_staking_contract_CreateStakingContractEvent) - [Struct `UpdateVoterEvent`](#0x1_staking_contract_UpdateVoterEvent) - [Struct `ResetLockupEvent`](#0x1_staking_contract_ResetLockupEvent) @@ -46,7 +57,6 @@ pool. - [Struct `SwitchOperatorEvent`](#0x1_staking_contract_SwitchOperatorEvent) - [Struct `AddDistributionEvent`](#0x1_staking_contract_AddDistributionEvent) - [Struct `DistributeEvent`](#0x1_staking_contract_DistributeEvent) -- [Struct `SetBeneficiaryForOperator`](#0x1_staking_contract_SetBeneficiaryForOperator) - [Constants](#@Constants_0) - [Function `stake_pool_address`](#0x1_staking_contract_stake_pool_address) - [Function `last_recorded_principal`](#0x1_staking_contract_last_recorded_principal) @@ -333,6 +343,52 @@ pool. +
+Fields + + +
+
+staker: address +
+
+ +
+
+operator: address +
+
+ +
+
+old_commission_percentage: u64 +
+
+ +
+
+new_commission_percentage: u64 +
+
+ +
+
+ + +
+ + + +## Struct `UpdateCommission` + + + +
#[event]
+struct UpdateCommission has drop, store
+
+ + +
Fields @@ -395,13 +451,14 @@ pool.
- + -## Struct `CreateStakingContractEvent` +## Struct `CreateStakingContract` -
struct CreateStakingContractEvent has drop, store
+
#[event]
+struct CreateStakingContract has drop, store
 
@@ -446,13 +503,14 @@ pool.
- + -## Struct `UpdateVoterEvent` +## Struct `UpdateVoter` -
struct UpdateVoterEvent has drop, store
+
#[event]
+struct UpdateVoter has drop, store
 
@@ -491,13 +549,14 @@ pool.
- + -## Struct `ResetLockupEvent` +## Struct `ResetLockup` -
struct ResetLockupEvent has drop, store
+
#[event]
+struct ResetLockup has drop, store
 
@@ -524,13 +583,14 @@ pool.
- + -## Struct `AddStakeEvent` +## Struct `AddStake` -
struct AddStakeEvent has drop, store
+
#[event]
+struct AddStake has drop, store
 
@@ -563,13 +623,14 @@ pool.
- + -## Struct `RequestCommissionEvent` +## Struct `RequestCommission` -
struct RequestCommissionEvent has drop, store
+
#[event]
+struct RequestCommission has drop, store
 
@@ -608,13 +669,14 @@ pool.
- + -## Struct `UnlockStakeEvent` +## Struct `UnlockStake` -
struct UnlockStakeEvent has drop, store
+
#[event]
+struct UnlockStake has drop, store
 
@@ -653,13 +715,14 @@ pool.
- + -## Struct `SwitchOperatorEvent` +## Struct `SwitchOperator` -
struct SwitchOperatorEvent has drop, store
+
#[event]
+struct SwitchOperator has drop, store
 
@@ -692,13 +755,14 @@ pool.
- + -## Struct `AddDistributionEvent` +## Struct `AddDistribution` -
struct AddDistributionEvent has drop, store
+
#[event]
+struct AddDistribution has drop, store
 
@@ -731,13 +795,14 @@ pool.
- + -## Struct `DistributeEvent` +## Struct `Distribute` -
struct DistributeEvent has drop, store
+
#[event]
+struct Distribute has drop, store
 
@@ -814,6 +879,387 @@ pool. +
+ + + +## Struct `CreateStakingContractEvent` + + + +
struct CreateStakingContractEvent has drop, store
+
+ + + +
+Fields + + +
+
+operator: address +
+
+ +
+
+voter: address +
+
+ +
+
+pool_address: address +
+
+ +
+
+principal: u64 +
+
+ +
+
+commission_percentage: u64 +
+
+ +
+
+ + +
+ + + +## Struct `UpdateVoterEvent` + + + +
struct UpdateVoterEvent has drop, store
+
+ + + +
+Fields + + +
+
+operator: address +
+
+ +
+
+pool_address: address +
+
+ +
+
+old_voter: address +
+
+ +
+
+new_voter: address +
+
+ +
+
+ + +
+ + + +## Struct `ResetLockupEvent` + + + +
struct ResetLockupEvent has drop, store
+
+ + + +
+Fields + + +
+
+operator: address +
+
+ +
+
+pool_address: address +
+
+ +
+
+ + +
+ + + +## Struct `AddStakeEvent` + + + +
struct AddStakeEvent has drop, store
+
+ + + +
+Fields + + +
+
+operator: address +
+
+ +
+
+pool_address: address +
+
+ +
+
+amount: u64 +
+
+ +
+
+ + +
+ + + +## Struct `RequestCommissionEvent` + + + +
struct RequestCommissionEvent has drop, store
+
+ + + +
+Fields + + +
+
+operator: address +
+
+ +
+
+pool_address: address +
+
+ +
+
+accumulated_rewards: u64 +
+
+ +
+
+commission_amount: u64 +
+
+ +
+
+ + +
+ + + +## Struct `UnlockStakeEvent` + + + +
struct UnlockStakeEvent has drop, store
+
+ + + +
+Fields + + +
+
+operator: address +
+
+ +
+
+pool_address: address +
+
+ +
+
+amount: u64 +
+
+ +
+
+commission_paid: u64 +
+
+ +
+
+ + +
+ + + +## Struct `SwitchOperatorEvent` + + + +
struct SwitchOperatorEvent has drop, store
+
+ + + +
+Fields + + +
+
+old_operator: address +
+
+ +
+
+new_operator: address +
+
+ +
+
+pool_address: address +
+
+ +
+
+ + +
+ + + +## Struct `AddDistributionEvent` + + + +
struct AddDistributionEvent has drop, store
+
+ + + +
+Fields + + +
+
+operator: address +
+
+ +
+
+pool_address: address +
+
+ +
+
+amount: u64 +
+
+ +
+
+ + +
+ + + +## Struct `DistributeEvent` + + + +
struct DistributeEvent has drop, store
+
+ + + +
+Fields + + +
+
+operator: address +
+
+ +
+
+pool_address: address +
+
+ +
+
+recipient: address +
+
+ +
+
+amount: u64 +
+
+ +
+
+ +
@@ -1285,6 +1731,9 @@ Staker can call this function to create a simple staking contract with a specifi signer_cap: stake_pool_signer_cap, }); + if (std::features::module_event_migration_enabled()) { + emit(CreateStakingContract { operator, voter, pool_address, principal, commission_percentage }); + }; emit_event( &mut store.create_staking_contract_events, CreateStakingContractEvent { operator, voter, pool_address, principal, commission_percentage }, @@ -1326,6 +1775,9 @@ Add more stake to an existing staking contract. staking_contract.principal = staking_contract.principal + amount; let pool_address = staking_contract.pool_address; + if (std::features::module_event_migration_enabled()) { + emit(AddStake { operator, pool_address, amount }); + }; emit_event( &mut store.add_stake_events, AddStakeEvent { operator, pool_address, amount }, @@ -1363,10 +1815,14 @@ Convenient function to allow the staker to update the voter address in a staking let old_voter = stake::get_delegated_voter(pool_address); stake::set_delegated_voter_with_cap(&staking_contract.owner_cap, new_voter); + if (std::features::module_event_migration_enabled()) { + emit(UpdateVoter { operator, pool_address, old_voter, new_voter }); + }; emit_event( &mut store.update_voter_events, UpdateVoterEvent { operator, pool_address, old_voter, new_voter }, ); + }
@@ -1399,6 +1855,9 @@ Convenient function to allow the staker to reset their stake pool's lockup perio let pool_address = staking_contract.pool_address; stake::increase_lockup_with_cap(&staking_contract.owner_cap); + if (std::features::module_event_migration_enabled()) { + emit(ResetLockup { operator, pool_address }); + }; emit_event(&mut store.reset_lockup_events, ResetLockupEvent { operator, pool_address }); }
@@ -1424,7 +1883,11 @@ TODO: fix the typo in function name. commision -> commission Implementation -
public entry fun update_commision(staker: &signer, operator: address, new_commission_percentage: u64) acquires Store, StakingGroupUpdateCommissionEvent, BeneficiaryForOperator {
+
public entry fun update_commision(
+    staker: &signer,
+    operator: address,
+    new_commission_percentage: u64
+) acquires Store, BeneficiaryForOperator, StakingGroupUpdateCommissionEvent {
     assert!(
         new_commission_percentage >= 0 && new_commission_percentage <= 100,
         error::invalid_argument(EINVALID_COMMISSION_PERCENTAGE),
@@ -1445,7 +1908,19 @@ TODO: fix the typo in function name. commision -> commission
     let old_commission_percentage = staking_contract.commission_percentage;
     staking_contract.commission_percentage = new_commission_percentage;
     if (!exists<StakingGroupUpdateCommissionEvent>(staker_address)) {
-        move_to(staker, StakingGroupUpdateCommissionEvent { update_commission_events: account::new_event_handle<UpdateCommissionEvent>(staker)})
+        move_to(
+            staker,
+            StakingGroupUpdateCommissionEvent {
+                update_commission_events: account::new_event_handle<UpdateCommissionEvent>(
+                    staker
+                )
+            }
+        )
+    };
+    if (std::features::module_event_migration_enabled()) {
+        emit(
+            UpdateCommission { staker: staker_address, operator, old_commission_percentage, new_commission_percentage }
+        );
     };
     emit_event(
         &mut borrow_global_mut<StakingGroupUpdateCommissionEvent>(staker_address).update_commission_events,
@@ -1477,7 +1952,11 @@ Only staker, operator or beneficiary can call this.
 Implementation
 
 
-
public entry fun request_commission(account: &signer, staker: address, operator: address) acquires Store, BeneficiaryForOperator {
+
public entry fun request_commission(
+    account: &signer,
+    staker: address,
+    operator: address
+) acquires Store, BeneficiaryForOperator {
     let account_addr = signer::address_of(account);
     assert!(
         account_addr == staker || account_addr == operator || account_addr == beneficiary_for_operator(operator),
@@ -1547,6 +2026,9 @@ Only staker, operator or beneficiary can call this.
     stake::unlock_with_cap(commission_amount, &staking_contract.owner_cap);
 
     let pool_address = staking_contract.pool_address;
+    if (std::features::module_event_migration_enabled()) {
+        emit(RequestCommission { operator, pool_address, accumulated_rewards, commission_amount });
+    };
     emit_event(
         request_commission_events,
         RequestCommissionEvent { operator, pool_address, accumulated_rewards, commission_amount },
@@ -1577,7 +2059,11 @@ This also triggers paying commission to the operator for accounting simplicity.
 Implementation
 
 
-
public entry fun unlock_stake(staker: &signer, operator: address, amount: u64) acquires Store, BeneficiaryForOperator {
+
public entry fun unlock_stake(
+    staker: &signer,
+    operator: address,
+    amount: u64
+) acquires Store, BeneficiaryForOperator {
     // Short-circuit if amount is 0.
     if (amount == 0) return;
 
@@ -1608,14 +2094,16 @@ This also triggers paying commission to the operator for accounting simplicity.
     staking_contract.principal = staking_contract.principal - amount;
 
     // Record a distribution for the staker.
-    add_distribution(
-        operator, staking_contract, staker_address, amount, &mut store.add_distribution_events);
+    add_distribution(operator, staking_contract, staker_address, amount, &mut store.add_distribution_events);
 
     // Request to unlock the distribution amount from the stake pool.
     // This won't become fully unlocked until the stake pool's lockup expires.
     stake::unlock_with_cap(amount, &staking_contract.owner_cap);
 
     let pool_address = staking_contract.pool_address;
+    if (std::features::module_event_migration_enabled()) {
+        emit(UnlockStake { pool_address, operator, amount, commission_paid });
+    };
     emit_event(
         &mut store.unlock_stake_events,
         UnlockStakeEvent { pool_address, operator, amount, commission_paid },
@@ -1743,6 +2231,9 @@ Allows staker to switch operator without going through the lenghthy process to u
 
     let pool_address = staking_contract.pool_address;
     simple_map::add(staking_contracts, new_operator, staking_contract);
+    if (std::features::module_event_migration_enabled()) {
+        emit(SwitchOperator { pool_address, old_operator, new_operator });
+    };
     emit_event(
         &mut store.switch_operator_events,
         SwitchOperatorEvent { pool_address, old_operator, new_operator }
@@ -1772,7 +2263,10 @@ the beneficiary. An operator can set one beneficiary for staking contract pools,
 Implementation
 
 
-
public entry fun set_beneficiary_for_operator(operator: &signer, new_beneficiary: address) acquires BeneficiaryForOperator {
+
public entry fun set_beneficiary_for_operator(
+    operator: &signer,
+    new_beneficiary: address
+) acquires BeneficiaryForOperator {
     assert!(features::operator_beneficiary_change_enabled(), std::error::invalid_state(
         EOPERATOR_BENEFICIARY_CHANGE_NOT_SUPPORTED
     ));
@@ -1875,6 +2369,9 @@ Distribute all unlocked (inactive) funds according to distribution shares.
         };
         aptos_account::deposit_coins(recipient, coin::extract(&mut coins, amount_to_distribute));
 
+        if (std::features::module_event_migration_enabled()) {
+            emit(Distribute { operator, pool_address, recipient, amount: amount_to_distribute });
+        };
         emit_event(
             distribute_events,
             DistributeEvent { operator, pool_address, recipient, amount: amount_to_distribute }
@@ -1946,7 +2443,7 @@ Add a new distribution for recipient and amount to the
     staking_contract: &mut StakingContract,
     recipient: address,
     coins_amount: u64,
-    add_distribution_events: &mut EventHandle<AddDistributionEvent>,
+    add_distribution_events: &mut EventHandle<AddDistributionEvent>
 ) {
     let distribution_pool = &mut staking_contract.distribution_pool;
     let (_, _, _, total_distribution_amount) = stake::get_stake(staking_contract.pool_address);
@@ -1955,6 +2452,9 @@ Add a new distribution for recipient and amount to the
 
     pool_u64::buy_in(distribution_pool, recipient, coins_amount);
     let pool_address = staking_contract.pool_address;
+    if (std::features::module_event_migration_enabled()) {
+        emit(AddDistribution { operator, pool_address, amount: coins_amount });
+    };
     emit_event(
         add_distribution_events,
         AddDistributionEvent { operator, pool_address, amount: coins_amount }
@@ -2340,7 +2840,7 @@ Staking_contract exists the stacker/operator pair.
 let staking_contracts = global<Store>(staker).staking_contracts;
 let staking_contract = simple_map::spec_get(staking_contracts, operator);
 include ContractExistsAbortsIf;
-include GetStakingContractAmountsAbortsIf{staking_contract};
+include GetStakingContractAmountsAbortsIf { staking_contract };
 let pool_address = staking_contract.pool_address;
 let stake_pool = global<stake::StakePool>(pool_address);
 let active = coin::value(stake_pool.active);
@@ -2441,7 +2941,7 @@ Account is not frozen and sufficient to withdraw.
 
pragma aborts_if_is_partial;
 pragma verify_duration_estimate = 120;
 include PreconditionsInCreateContract;
-include WithdrawAbortsIf<AptosCoin> {account: staker};
+include WithdrawAbortsIf<AptosCoin> { account: staker };
 include CreateStakingContractWithCoinsAbortsIfAndEnsures;
 
@@ -2490,7 +2990,7 @@ Staking_contract exists the stacker/operator pair. include ContractExistsAbortsIf { staker: staker_address }; let store = global<Store>(staker_address); let staking_contract = simple_map::spec_get(store.staking_contracts, operator); -include WithdrawAbortsIf<AptosCoin>{account: staker}; +include WithdrawAbortsIf<AptosCoin> { account: staker }; let balance = global<coin::CoinStore<AptosCoin>>(staker_address).coin.value; let post post_coin = global<coin::CoinStore<AptosCoin>>(staker_address).coin.value; ensures post_coin == balance - amount; @@ -2518,7 +3018,7 @@ Staking_contract exists the stacker/operator pair.
let staker_address = signer::address_of(staker);
-include UpdateVoterSchema {staker: staker_address};
+include UpdateVoterSchema { staker: staker_address };
 let post store = global<Store>(staker_address);
 let post staking_contract = simple_map::spec_get(store.staking_contracts, operator);
 let post pool_address = staking_contract.owner_cap.pool_address;
@@ -2543,8 +3043,8 @@ Only active validator can update locked_until_secs.
 
 
let staker_address = signer::address_of(staker);
 // This enforces high-level requirement 5:
-include ContractExistsAbortsIf{staker: staker_address};
-include IncreaseLockupWithCapAbortsIf{staker: staker_address};
+include ContractExistsAbortsIf { staker: staker_address };
+include IncreaseLockupWithCapAbortsIf { staker: staker_address };
 
@@ -2563,7 +3063,7 @@ Only active validator can update locked_until_secs.
pragma verify = false;
 let staker_address = signer::address_of(staker);
 aborts_if new_commission_percentage > 100;
-include ContractExistsAbortsIf{staker: staker_address};
+include ContractExistsAbortsIf { staker: staker_address };
 
@@ -2582,7 +3082,7 @@ Only staker or operator can call this.
pragma verify = false;
 let account_addr = signer::address_of(account);
-include ContractExistsAbortsIf{staker};
+include ContractExistsAbortsIf { staker };
 aborts_if account_addr != staker && account_addr != operator;
 
@@ -2619,7 +3119,7 @@ Only staker or operator can call this.
pragma verify = false;
 requires amount > 0;
 let staker_address = signer::address_of(staker);
-include ContractExistsAbortsIf{staker: staker_address};
+include ContractExistsAbortsIf { staker: staker_address };
 
@@ -2642,7 +3142,7 @@ Staking_contract exists the stacker/operator pair. let staker_address = signer::address_of(staker); let staking_contracts = global<Store>(staker_address).staking_contracts; let staking_contract = simple_map::spec_get(staking_contracts, operator); -include ContractExistsAbortsIf{staker: staker_address}; +include ContractExistsAbortsIf { staker: staker_address };
@@ -2661,7 +3161,7 @@ Staking_contract exists the stacker/operator pair.
pragma aborts_if_is_partial;
 let staker_address = signer::address_of(staker);
-include ContractExistsAbortsIf{staker: staker_address, operator: old_operator};
+include ContractExistsAbortsIf { staker: staker_address, operator: old_operator };
 
@@ -2680,7 +3180,7 @@ Staking_contract exists the stacker/operator pair.
pragma verify = false;
 let staker_address = signer::address_of(staker);
-include ContractExistsAbortsIf{staker: staker_address, operator: old_operator};
+include ContractExistsAbortsIf { staker: staker_address, operator: old_operator };
 let store = global<Store>(staker_address);
 let staking_contracts = store.staking_contracts;
 aborts_if simple_map::spec_contains_key(staking_contracts, new_operator);
@@ -2816,12 +3316,13 @@ The StakePool exists under the pool_address of StakingContract.
 
 
 
-
include stake::ResourceRequirement;
+
pragma verify_duration_estimate = 120;
+include stake::ResourceRequirement;
 let staker_address = signer::address_of(staker);
 let seed_0 = bcs::to_bytes(staker_address);
 let seed_1 = concat(concat(concat(seed_0, bcs::to_bytes(operator)), SALT), contract_creation_seed);
 let resource_addr = account::spec_create_resource_address(staker_address, seed_1);
-include CreateStakePoolAbortsIf {resource_addr};
+include CreateStakePoolAbortsIf { resource_addr };
 ensures exists<account::Account>(resource_addr);
 let post post_account = global<account::Account>(resource_addr);
 ensures post_account.authentication_key == account::ZERO_AUTH_KEY;
@@ -2980,7 +3481,9 @@ a staking_contract exists for the staker/operator pair.
     let config = global<staking_config::StakingConfig>(@aptos_framework);
     let stake_pool = global<stake::StakePool>(pool_address);
     let old_locked_until_secs = stake_pool.locked_until_secs;
-    let seconds = global<timestamp::CurrentTimeMicroseconds>(@aptos_framework).microseconds / timestamp::MICRO_CONVERSION_FACTOR;
+    let seconds = global<timestamp::CurrentTimeMicroseconds>(
+        @aptos_framework
+    ).microseconds / timestamp::MICRO_CONVERSION_FACTOR;
     let new_locked_until_secs = seconds + config.recurring_lockup_duration_secs;
     aborts_if seconds + config.recurring_lockup_duration_secs > MAX_U64;
     aborts_if old_locked_until_secs > new_locked_until_secs || old_locked_until_secs == new_locked_until_secs;
@@ -3033,7 +3536,9 @@ a staking_contract exists for the staker/operator pair.
 
schema PreconditionsInCreateContract {
     requires exists<stake::ValidatorPerformance>(@aptos_framework);
     requires exists<stake::ValidatorSet>(@aptos_framework);
-    requires exists<staking_config::StakingRewardsConfig>(@aptos_framework) || !std::features::spec_periodical_reward_rate_decrease_enabled();
+    requires exists<staking_config::StakingRewardsConfig>(
+        @aptos_framework
+    ) || !std::features::spec_periodical_reward_rate_decrease_enabled();
     requires exists<stake::ValidatorFees>(@aptos_framework);
     requires exists<aptos_framework::timestamp::CurrentTimeMicroseconds>(@aptos_framework);
     requires exists<stake::AptosCoinCapabilities>(@aptos_framework);
@@ -3052,7 +3557,9 @@ a staking_contract exists for the staker/operator pair.
     voter: address;
     contract_creation_seed: vector<u8>;
     let acc = global<account::Account>(resource_addr);
-    aborts_if exists<account::Account>(resource_addr) && (len(acc.signer_capability_offer.for.vec) != 0 || acc.sequence_number != 0);
+    aborts_if exists<account::Account>(resource_addr) && (len(
+        acc.signer_capability_offer.for.vec
+    ) != 0 || acc.sequence_number != 0);
     aborts_if !exists<account::Account>(resource_addr) && len(bcs::to_bytes(resource_addr)) != 32;
     aborts_if len(account::ZERO_AUTH_KEY) != 32;
     aborts_if exists<stake::ValidatorConfig>(resource_addr);
@@ -3060,7 +3567,9 @@ a staking_contract exists for the staker/operator pair.
     aborts_if exists<stake::AllowedValidators>(@aptos_framework) && !contains(allowed.accounts, resource_addr);
     aborts_if exists<stake::StakePool>(resource_addr);
     aborts_if exists<stake::OwnerCapability>(resource_addr);
-    aborts_if exists<account::Account>(resource_addr) && acc.guid_creation_num + 12 >= account::MAX_GUID_CREATION_NUM;
+    aborts_if exists<account::Account>(
+        resource_addr
+    ) && acc.guid_creation_num + 12 >= account::MAX_GUID_CREATION_NUM;
 }
 
diff --git a/aptos-move/framework/aptos-framework/doc/vesting.md b/aptos-move/framework/aptos-framework/doc/vesting.md index 64d7d85cee2c0..c4c35ec54ef41 100644 --- a/aptos-move/framework/aptos-framework/doc/vesting.md +++ b/aptos-move/framework/aptos-framework/doc/vesting.md @@ -45,6 +45,16 @@ withdrawable, admin can call admin_withdraw to withdraw all funds to the vesting - [Resource `VestingContract`](#0x1_vesting_VestingContract) - [Resource `VestingAccountManagement`](#0x1_vesting_VestingAccountManagement) - [Resource `AdminStore`](#0x1_vesting_AdminStore) +- [Struct `CreateVestingContract`](#0x1_vesting_CreateVestingContract) +- [Struct `UpdateOperator`](#0x1_vesting_UpdateOperator) +- [Struct `UpdateVoter`](#0x1_vesting_UpdateVoter) +- [Struct `ResetLockup`](#0x1_vesting_ResetLockup) +- [Struct `SetBeneficiary`](#0x1_vesting_SetBeneficiary) +- [Struct `UnlockRewards`](#0x1_vesting_UnlockRewards) +- [Struct `Vest`](#0x1_vesting_Vest) +- [Struct `Distribute`](#0x1_vesting_Distribute) +- [Struct `Terminate`](#0x1_vesting_Terminate) +- [Struct `AdminWithdraw`](#0x1_vesting_AdminWithdraw) - [Struct `CreateVestingContractEvent`](#0x1_vesting_CreateVestingContractEvent) - [Struct `UpdateOperatorEvent`](#0x1_vesting_UpdateOperatorEvent) - [Struct `UpdateVoterEvent`](#0x1_vesting_UpdateVoterEvent) @@ -156,6 +166,7 @@ withdrawable, admin can call admin_withdraw to withdraw all funds to the vesting use 0x1::coin; use 0x1::error; use 0x1::event; +use 0x1::features; use 0x1::fixed_point32; use 0x1::math64; use 0x1::pool_u64; @@ -454,6 +465,490 @@ withdrawable, admin can call admin_withdraw to withdraw all funds to the vesting + + + + +## Struct `CreateVestingContract` + + + +
#[event]
+struct CreateVestingContract has drop, store
+
+ + + +
+Fields + + +
+
+operator: address +
+
+ +
+
+voter: address +
+
+ +
+
+grant_amount: u64 +
+
+ +
+
+withdrawal_address: address +
+
+ +
+
+vesting_contract_address: address +
+
+ +
+
+staking_pool_address: address +
+
+ +
+
+commission_percentage: u64 +
+
+ +
+
+ + +
+ + + +## Struct `UpdateOperator` + + + +
#[event]
+struct UpdateOperator has drop, store
+
+ + + +
+Fields + + +
+
+admin: address +
+
+ +
+
+vesting_contract_address: address +
+
+ +
+
+staking_pool_address: address +
+
+ +
+
+old_operator: address +
+
+ +
+
+new_operator: address +
+
+ +
+
+commission_percentage: u64 +
+
+ +
+
+ + +
+ + + +## Struct `UpdateVoter` + + + +
#[event]
+struct UpdateVoter has drop, store
+
+ + + +
+Fields + + +
+
+admin: address +
+
+ +
+
+vesting_contract_address: address +
+
+ +
+
+staking_pool_address: address +
+
+ +
+
+old_voter: address +
+
+ +
+
+new_voter: address +
+
+ +
+
+ + +
+ + + +## Struct `ResetLockup` + + + +
#[event]
+struct ResetLockup has drop, store
+
+ + + +
+Fields + + +
+
+admin: address +
+
+ +
+
+vesting_contract_address: address +
+
+ +
+
+staking_pool_address: address +
+
+ +
+
+new_lockup_expiration_secs: u64 +
+
+ +
+
+ + +
+ + + +## Struct `SetBeneficiary` + + + +
#[event]
+struct SetBeneficiary has drop, store
+
+ + + +
+Fields + + +
+
+admin: address +
+
+ +
+
+vesting_contract_address: address +
+
+ +
+
+shareholder: address +
+
+ +
+
+old_beneficiary: address +
+
+ +
+
+new_beneficiary: address +
+
+ +
+
+ + +
+ + + +## Struct `UnlockRewards` + + + +
#[event]
+struct UnlockRewards has drop, store
+
+ + + +
+Fields + + +
+
+admin: address +
+
+ +
+
+vesting_contract_address: address +
+
+ +
+
+staking_pool_address: address +
+
+ +
+
+amount: u64 +
+
+ +
+
+ + +
+ + + +## Struct `Vest` + + + +
#[event]
+struct Vest has drop, store
+
+ + + +
+Fields + + +
+
+admin: address +
+
+ +
+
+vesting_contract_address: address +
+
+ +
+
+staking_pool_address: address +
+
+ +
+
+period_vested: u64 +
+
+ +
+
+amount: u64 +
+
+ +
+
+ + +
+ + + +## Struct `Distribute` + + + +
#[event]
+struct Distribute has drop, store
+
+ + + +
+Fields + + +
+
+admin: address +
+
+ +
+
+vesting_contract_address: address +
+
+ +
+
+amount: u64 +
+
+ +
+
+ + +
+ + + +## Struct `Terminate` + + + +
#[event]
+struct Terminate has drop, store
+
+ + + +
+Fields + + +
+
+admin: address +
+
+ +
+
+vesting_contract_address: address +
+
+ +
+
+ + +
+ + + +## Struct `AdminWithdraw` + + + +
#[event]
+struct AdminWithdraw has drop, store
+
+ + + +
+Fields + + +
+
+admin: address +
+
+ +
+
+vesting_contract_address: address +
+
+ +
+
+amount: u64 +
+
+ +
+
+ +
@@ -1569,7 +2064,10 @@ This returns 0x0 if no shareholder is found for the given beneficiary / the addr Implementation -
public fun shareholder(vesting_contract_address: address, shareholder_or_beneficiary: address): address acquires VestingContract {
+
public fun shareholder(
+    vesting_contract_address: address,
+    shareholder_or_beneficiary: address
+): address acquires VestingContract {
     assert_active_vesting_contract(vesting_contract_address);
 
     let shareholders = &shareholders(vesting_contract_address);
@@ -1713,6 +2211,19 @@ Create a vesting contract with a given configurations.
     let contract_address = signer::address_of(&contract_signer);
     let admin_store = borrow_global_mut<AdminStore>(admin_address);
     vector::push_back(&mut admin_store.vesting_contracts, contract_address);
+    if (std::features::module_event_migration_enabled()) {
+        emit(
+            CreateVestingContract {
+                operator,
+                voter,
+                withdrawal_address,
+                grant_amount,
+                vesting_contract_address: contract_address,
+                staking_pool_address: pool_address,
+                commission_percentage,
+            },
+        );
+    };
     emit_event(
         &mut admin_store.create_events,
         CreateVestingContractEvent {
@@ -1871,6 +2382,17 @@ Unlock any vested portion of the grant.
     vesting_schedule.last_vested_period = next_period_to_vest;
     unlock_stake(vesting_contract, vested_amount);
 
+    if (std::features::module_event_migration_enabled()) {
+        emit(
+            Vest {
+                admin: vesting_contract.admin,
+                vesting_contract_address: contract_address,
+                staking_pool_address: vesting_contract.staking.pool_address,
+                period_vested: next_period_to_vest,
+                amount: vested_amount,
+            },
+        );
+    };
     emit_event(
         &mut vesting_contract.vest_events,
         VestEvent {
@@ -1947,7 +2469,7 @@ Distribute any withdrawable stake from the stake pool.
         return
     };
 
-    // Distribute coins to all shareholders in the vesting contract.
+    // Distribute coins to all shareholders in the vesting contract.
     let grant_pool = &vesting_contract.grant_pool;
     let shareholders = &pool_u64::shareholders(grant_pool);
     vector::for_each_ref(shareholders, |shareholder| {
@@ -1966,6 +2488,15 @@ Distribute any withdrawable stake from the stake pool.
         coin::destroy_zero(coins);
     };
 
+    if (std::features::module_event_migration_enabled()) {
+        emit(
+            Distribute {
+                admin: vesting_contract.admin,
+                vesting_contract_address: contract_address,
+                amount: total_distribution_amount,
+            },
+        );
+    };
     emit_event(
         &mut vesting_contract.distribute_events,
         DistributeEvent {
@@ -2032,7 +2563,7 @@ Terminate the vesting contract and send all funds back to the withdrawal address
 
public entry fun terminate_vesting_contract(admin: &signer, contract_address: address) acquires VestingContract {
     assert_active_vesting_contract(contract_address);
 
-    // Distribute all withdrawable coins, which should have been from previous rewards withdrawal or vest.
+    // Distribute all withdrawable coins, which should have been from previous rewards withdrawal or vest.
     distribute(contract_address);
 
     let vesting_contract = borrow_global_mut<VestingContract>(contract_address);
@@ -2045,6 +2576,14 @@ Terminate the vesting contract and send all funds back to the withdrawal address
     vesting_contract.remaining_grant = 0;
     unlock_stake(vesting_contract, active_stake);
 
+    if (std::features::module_event_migration_enabled()) {
+        emit(
+            Terminate {
+                admin: vesting_contract.admin,
+                vesting_contract_address: contract_address,
+            },
+        );
+    };
     emit_event(
         &mut vesting_contract.terminate_events,
         TerminateEvent {
@@ -2078,7 +2617,10 @@ has already been terminated.
 
 
public entry fun admin_withdraw(admin: &signer, contract_address: address) acquires VestingContract {
     let vesting_contract = borrow_global<VestingContract>(contract_address);
-    assert!(vesting_contract.state == VESTING_POOL_TERMINATED, error::invalid_state(EVESTING_CONTRACT_STILL_ACTIVE));
+    assert!(
+        vesting_contract.state == VESTING_POOL_TERMINATED,
+        error::invalid_state(EVESTING_CONTRACT_STILL_ACTIVE)
+    );
 
     let vesting_contract = borrow_global_mut<VestingContract>(contract_address);
     verify_admin(admin, vesting_contract);
@@ -2090,6 +2632,15 @@ has already been terminated.
     };
     aptos_account::deposit_coins(vesting_contract.withdrawal_address, coins);
 
+    if (std::features::module_event_migration_enabled()) {
+        emit(
+            AdminWithdraw {
+                admin: vesting_contract.admin,
+                vesting_contract_address: contract_address,
+                amount,
+            },
+        );
+    };
     emit_event(
         &mut vesting_contract.admin_withdraw_events,
         AdminWithdrawEvent {
@@ -2134,6 +2685,18 @@ has already been terminated.
     vesting_contract.staking.operator = new_operator;
     vesting_contract.staking.commission_percentage = commission_percentage;
 
+    if (std::features::module_event_migration_enabled()) {
+        emit(
+            UpdateOperator {
+                admin: vesting_contract.admin,
+                vesting_contract_address: contract_address,
+                staking_pool_address: vesting_contract.staking.pool_address,
+                old_operator,
+                new_operator,
+                commission_percentage,
+            },
+        );
+    };
     emit_event(
         &mut vesting_contract.update_operator_events,
         UpdateOperatorEvent {
@@ -2243,6 +2806,17 @@ has already been terminated.
     staking_contract::update_voter(contract_signer, vesting_contract.staking.operator, new_voter);
     vesting_contract.staking.voter = new_voter;
 
+    if (std::features::module_event_migration_enabled()) {
+        emit(
+            UpdateVoter {
+                admin: vesting_contract.admin,
+                vesting_contract_address: contract_address,
+                staking_pool_address: vesting_contract.staking.pool_address,
+                old_voter,
+                new_voter,
+            },
+        );
+    };
     emit_event(
         &mut vesting_contract.update_voter_events,
         UpdateVoterEvent {
@@ -2284,6 +2858,16 @@ has already been terminated.
     let contract_signer = &get_vesting_account_signer_internal(vesting_contract);
     staking_contract::reset_lockup(contract_signer, vesting_contract.staking.operator);
 
+    if (std::features::module_event_migration_enabled()) {
+        emit(
+            ResetLockup {
+                admin: vesting_contract.admin,
+                vesting_contract_address: contract_address,
+                staking_pool_address: vesting_contract.staking.pool_address,
+                new_lockup_expiration_secs: stake::get_lockup_secs(vesting_contract.staking.pool_address),
+            },
+        );
+    };
     emit_event(
         &mut vesting_contract.reset_lockup_events,
         ResetLockupEvent {
@@ -2337,6 +2921,17 @@ has already been terminated.
         simple_map::add(beneficiaries, shareholder, new_beneficiary);
     };
 
+    if (std::features::module_event_migration_enabled()) {
+        emit(
+            SetBeneficiary {
+                admin: vesting_contract.admin,
+                vesting_contract_address: contract_address,
+                shareholder,
+                old_beneficiary,
+                new_beneficiary,
+            },
+        );
+    };
     emit_event(
         &mut vesting_contract.set_beneficiary_events,
         SetBeneficiaryEvent {
diff --git a/aptos-move/framework/aptos-framework/doc/voting.md b/aptos-move/framework/aptos-framework/doc/voting.md
index 6fb71c9687c5c..26393d14c158f 100644
--- a/aptos-move/framework/aptos-framework/doc/voting.md
+++ b/aptos-move/framework/aptos-framework/doc/voting.md
@@ -29,10 +29,13 @@ the resolution process.
 -  [Struct `Proposal`](#0x1_voting_Proposal)
 -  [Resource `VotingForum`](#0x1_voting_VotingForum)
 -  [Struct `VotingEvents`](#0x1_voting_VotingEvents)
+-  [Struct `CreateProposal`](#0x1_voting_CreateProposal)
+-  [Struct `RegisterForum`](#0x1_voting_RegisterForum)
+-  [Struct `Vote`](#0x1_voting_Vote)
+-  [Struct `ResolveProposal`](#0x1_voting_ResolveProposal)
 -  [Struct `CreateProposalEvent`](#0x1_voting_CreateProposalEvent)
 -  [Struct `RegisterForumEvent`](#0x1_voting_RegisterForumEvent)
 -  [Struct `VoteEvent`](#0x1_voting_VoteEvent)
--  [Struct `ResolveProposal`](#0x1_voting_ResolveProposal)
 -  [Constants](#@Constants_0)
 -  [Function `register`](#0x1_voting_register)
 -  [Function `create_proposal`](#0x1_voting_create_proposal)
@@ -92,6 +95,7 @@ the resolution process.
 use 0x1::bcs;
 use 0x1::error;
 use 0x1::event;
+use 0x1::features;
 use 0x1::from_bcs;
 use 0x1::option;
 use 0x1::signer;
@@ -296,13 +300,14 @@ Extra metadata (e.g. description, code url) can be part of the ProposalType stru
 
 
 
-
+
 
-## Struct `CreateProposalEvent`
+## Struct `CreateProposal`
 
 
 
-
struct CreateProposalEvent has drop, store
+
#[event]
+struct CreateProposal has drop, store
 
@@ -353,13 +358,14 @@ Extra metadata (e.g. description, code url) can be part of the ProposalType stru - + -## Struct `RegisterForumEvent` +## Struct `RegisterForum` -
struct RegisterForumEvent has drop, store
+
#[event]
+struct RegisterForum has drop, store
 
@@ -386,13 +392,14 @@ Extra metadata (e.g. description, code url) can be part of the ProposalType stru - + -## Struct `VoteEvent` +## Struct `Vote` -
struct VoteEvent has drop, store
+
#[event]
+struct Vote has drop, store
 
@@ -425,7 +432,8 @@ Extra metadata (e.g. description, code url) can be part of the ProposalType stru -
struct ResolveProposal has drop, store
+
#[event]
+struct ResolveProposal has drop, store
 
@@ -462,6 +470,129 @@ Extra metadata (e.g. description, code url) can be part of the ProposalType stru + + + + +## Struct `CreateProposalEvent` + + + +
struct CreateProposalEvent has drop, store
+
+ + + +
+Fields + + +
+
+proposal_id: u64 +
+
+ +
+
+early_resolution_vote_threshold: option::Option<u128> +
+
+ +
+
+execution_hash: vector<u8> +
+
+ +
+
+expiration_secs: u64 +
+
+ +
+
+metadata: simple_map::SimpleMap<string::String, vector<u8>> +
+
+ +
+
+min_vote_threshold: u128 +
+
+ +
+
+ + +
+ + + +## Struct `RegisterForumEvent` + + + +
struct RegisterForumEvent has drop, store
+
+ + + +
+Fields + + +
+
+hosting_account: address +
+
+ +
+
+proposal_type_info: type_info::TypeInfo +
+
+ +
+
+ + +
+ + + +## Struct `VoteEvent` + + + +
struct VoteEvent has drop, store
+
+ + + +
+Fields + + +
+
+proposal_id: u64 +
+
+ +
+
+num_votes: u64 +
+
+ +
+
+ +
@@ -679,6 +810,14 @@ Key used to track the resolvable time in the proposal's metadata. } }; + if (std::features::module_event_migration_enabled()) { + event::emit( + RegisterForum { + hosting_account: addr, + proposal_type_info: type_info::type_of<ProposalType>(), + }, + ); + }; event::emit_event<RegisterForumEvent>( &mut voting_forum.events.register_forum_events, RegisterForumEvent { @@ -811,8 +950,8 @@ resolve this proposal. // This value is by default false. We turn this value to true when we start executing the multi-step proposal. This value // will be used to disable further voting after we started executing the multi-step proposal. simple_map::add(&mut metadata, is_multi_step_in_execution_key, to_bytes(&false)); - // If the proposal is a single-step proposal, we check if the metadata passed by the client has the IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY key. - // If they have the key, we will remove it, because a single-step proposal that doesn't need this key. + // If the proposal is a single-step proposal, we check if the metadata passed by the client has the IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY key. + // If they have the key, we will remove it, because a single-step proposal that doesn't need this key. } else if (simple_map::contains_key(&mut metadata, &is_multi_step_in_execution_key)) { simple_map::remove(&mut metadata, &is_multi_step_in_execution_key); }; @@ -832,6 +971,18 @@ resolve this proposal. resolution_time_secs: 0, }); + if (std::features::module_event_migration_enabled()) { + event::emit( + CreateProposal { + proposal_id, + early_resolution_vote_threshold, + execution_hash, + expiration_secs, + metadata, + min_vote_threshold, + }, + ); + }; event::emit_event<CreateProposalEvent>( &mut voting_forum.events.create_proposal_events, CreateProposalEvent { @@ -893,8 +1044,10 @@ This guarantees that voting eligibility and voting power are controlled by the r assert!(!proposal.is_resolved, error::invalid_state(EPROPOSAL_ALREADY_RESOLVED)); // Assert this proposal is single-step, or if the proposal is multi-step, it is not in execution yet. assert!(!simple_map::contains_key(&proposal.metadata, &utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY)) - || *simple_map::borrow(&proposal.metadata, &utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY)) == to_bytes(&false), - error::invalid_state(EMULTI_STEP_PROPOSAL_IN_EXECUTION)); + || *simple_map::borrow(&proposal.metadata, &utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY)) == to_bytes( + &false + ), + error::invalid_state(EMULTI_STEP_PROPOSAL_IN_EXECUTION)); if (should_pass) { proposal.yes_votes = proposal.yes_votes + (num_votes as u128); @@ -911,6 +1064,9 @@ This guarantees that voting eligibility and voting power are controlled by the r simple_map::add(&mut proposal.metadata, key, timestamp_secs_bytes); }; + if (std::features::module_event_migration_enabled()) { + event::emit(Vote { proposal_id, num_votes }); + }; event::emit_event<VoteEvent>( &mut voting_forum.events.vote_events, VoteEvent { proposal_id, num_votes }, @@ -999,13 +1155,26 @@ there are more yes votes than no. If either of these conditions is not met, this let has_multi_step_key = simple_map::contains_key(&proposal.metadata, &multi_step_key); if (has_multi_step_key) { let is_multi_step_proposal = from_bcs::to_bool(*simple_map::borrow(&proposal.metadata, &multi_step_key)); - assert!(!is_multi_step_proposal, error::permission_denied(EMULTI_STEP_PROPOSAL_CANNOT_USE_SINGLE_STEP_RESOLVE_FUNCTION)); + assert!( + !is_multi_step_proposal, + error::permission_denied(EMULTI_STEP_PROPOSAL_CANNOT_USE_SINGLE_STEP_RESOLVE_FUNCTION) + ); }; let resolved_early = can_be_resolved_early(proposal); proposal.is_resolved = true; proposal.resolution_time_secs = timestamp::now_seconds(); + if (std::features::module_event_migration_enabled()) { + event::emit( + ResolveProposal { + proposal_id, + yes_votes: proposal.yes_votes, + no_votes: proposal.no_votes, + resolved_early, + }, + ); + }; event::emit_event<ResolveProposal>( &mut voting_forum.events.resolve_proposal_events, ResolveProposal { @@ -1060,16 +1229,24 @@ there are more yes votes than no. If either of these conditions is not met, this // Update the IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY key to indicate that the multi-step proposal is in execution. let multi_step_in_execution_key = utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY); if (simple_map::contains_key(&proposal.metadata, &multi_step_in_execution_key)) { - let is_multi_step_proposal_in_execution_value = simple_map::borrow_mut(&mut proposal.metadata, &multi_step_in_execution_key); + let is_multi_step_proposal_in_execution_value = simple_map::borrow_mut( + &mut proposal.metadata, + &multi_step_in_execution_key + ); *is_multi_step_proposal_in_execution_value = to_bytes(&true); }; let multi_step_key = utf8(IS_MULTI_STEP_PROPOSAL_KEY); - let is_multi_step = simple_map::contains_key(&proposal.metadata, &multi_step_key) && from_bcs::to_bool(*simple_map::borrow(&proposal.metadata, &multi_step_key)); + let is_multi_step = simple_map::contains_key(&proposal.metadata, &multi_step_key) && from_bcs::to_bool( + *simple_map::borrow(&proposal.metadata, &multi_step_key) + ); let next_execution_hash_is_empty = vector::length(&next_execution_hash) == 0; // Assert that if this proposal is single-step, the `next_execution_hash` parameter is empty. - assert!(is_multi_step || next_execution_hash_is_empty, error::invalid_argument(ESINGLE_STEP_PROPOSAL_CANNOT_HAVE_NEXT_EXECUTION_HASH)); + assert!( + is_multi_step || next_execution_hash_is_empty, + error::invalid_argument(ESINGLE_STEP_PROPOSAL_CANNOT_HAVE_NEXT_EXECUTION_HASH) + ); // If the `next_execution_hash` parameter is empty, it means that either // - this proposal is a single-step proposal, or @@ -1081,7 +1258,10 @@ there are more yes votes than no. If either of these conditions is not met, this // Set the `IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY` value to false upon successful resolution of the last step of a multi-step proposal. if (is_multi_step) { - let is_multi_step_proposal_in_execution_value = simple_map::borrow_mut(&mut proposal.metadata, &multi_step_in_execution_key); + let is_multi_step_proposal_in_execution_value = simple_map::borrow_mut( + &mut proposal.metadata, + &multi_step_in_execution_key + ); *is_multi_step_proposal_in_execution_value = to_bytes(&false); }; } else { @@ -1094,7 +1274,17 @@ there are more yes votes than no. If either of these conditions is not met, this // For multi-step proposals, we emit one `ResolveProposal` event per step in the multi-step proposal. This means // that we emit multiple `ResolveProposal` events for the same multi-step proposal. let resolved_early = can_be_resolved_early(proposal); - event::emit_event<ResolveProposal>( + if (std::features::module_event_migration_enabled()) { + event::emit( + ResolveProposal { + proposal_id, + yes_votes: proposal.yes_votes, + no_votes: proposal.no_votes, + resolved_early, + }, + ); + }; + event::emit_event( &mut voting_forum.events.resolve_proposal_events, ResolveProposal { proposal_id, @@ -1103,6 +1293,7 @@ there are more yes votes than no. If either of these conditions is not met, this resolved_early, }, ); + }
@@ -1127,7 +1318,7 @@ Return the next unassigned proposal id Implementation -
public fun next_proposal_id<ProposalType: store>(voting_forum_address: address,): u64 acquires VotingForum {
+
public fun next_proposal_id<ProposalType: store>(voting_forum_address: address, ): u64 acquires VotingForum {
     let voting_forum = borrow_global<VotingForum<ProposalType>>(voting_forum_address);
     voting_forum.next_proposal_id
 }
@@ -1153,7 +1344,10 @@ Return the next unassigned proposal id
 Implementation
 
 
-
public fun get_proposer<ProposalType: store>(voting_forum_address: address, proposal_id: u64): address acquires VotingForum {
+
public fun get_proposer<ProposalType: store>(
+    voting_forum_address: address,
+    proposal_id: u64
+): address acquires VotingForum {
     let proposal = get_proposal<ProposalType>(voting_forum_address, proposal_id);
     proposal.proposer
 }
@@ -1179,7 +1373,10 @@ Return the next unassigned proposal id
 Implementation
 
 
-
public fun is_voting_closed<ProposalType: store>(voting_forum_address: address, proposal_id: u64): bool acquires VotingForum {
+
public fun is_voting_closed<ProposalType: store>(
+    voting_forum_address: address,
+    proposal_id: u64
+): bool acquires VotingForum {
     let proposal = get_proposal<ProposalType>(voting_forum_address, proposal_id);
     can_be_resolved_early(proposal) || is_voting_period_over(proposal)
 }
@@ -1587,7 +1784,10 @@ Return true if the multi-step governance proposal is in execution.
     let voting_forum = borrow_global<VotingForum<ProposalType>>(voting_forum_address);
     let proposal = table::borrow(&voting_forum.proposals, proposal_id);
     let is_multi_step_in_execution_key = utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY);
-    assert!(simple_map::contains_key(&proposal.metadata, &is_multi_step_in_execution_key), error::invalid_argument(EPROPOSAL_IS_SINGLE_STEP));
+    assert!(
+        simple_map::contains_key(&proposal.metadata, &is_multi_step_in_execution_key),
+        error::invalid_argument(EPROPOSAL_IS_SINGLE_STEP)
+    );
     from_bcs::to_bool(*simple_map::borrow(&proposal.metadata, &is_multi_step_in_execution_key))
 }
 
diff --git a/aptos-move/framework/aptos-framework/sources/account.move b/aptos-move/framework/aptos-framework/sources/account.move index 489127d5e1546..cfdf8577fb304 100644 --- a/aptos-move/framework/aptos-framework/sources/account.move +++ b/aptos-move/framework/aptos-framework/sources/account.move @@ -77,10 +77,14 @@ module aptos_framework::account { /// knowledge of this new public key's associated secret key. These two signatures cannot be replayed in another /// context because they include the TXN's unique sequence number. struct RotationProofChallenge has copy, drop { - sequence_number: u64, // the sequence number of the account whose key is being rotated - originator: address, // the address of the account whose key is being rotated - current_auth_key: address, // the current authentication key of the account whose key is being rotated - new_public_key: vector, // the new public key that the account owner wants to rotate to + sequence_number: u64, + // the sequence number of the account whose key is being rotated + originator: address, + // the address of the account whose key is being rotated + current_auth_key: address, + // the current authentication key of the account whose key is being rotated + new_public_key: vector, + // the new public key that the account owner wants to rotate to } /// Deprecated struct - newest version is `RotationCapabilityOfferProofChallengeV2` @@ -168,6 +172,7 @@ module aptos_framework::account { /// Explicitly separate the GUID space between Object and Account to prevent accidental overlap. const MAX_GUID_CREATION_NUM: u64 = 0x4000000000000; + #[test_only] /// Create signer for testing, independently of an Aptos-style `Account`. public fun create_signer_for_test(addr: address): signer { create_signer(addr) } @@ -335,11 +340,17 @@ module aptos_framework::account { if (from_scheme == ED25519_SCHEME) { let from_pk = ed25519::new_unvalidated_public_key_from_bytes(from_public_key_bytes); let from_auth_key = ed25519::unvalidated_public_key_to_authentication_key(&from_pk); - assert!(account_resource.authentication_key == from_auth_key, error::unauthenticated(EWRONG_CURRENT_PUBLIC_KEY)); + assert!( + account_resource.authentication_key == from_auth_key, + error::unauthenticated(EWRONG_CURRENT_PUBLIC_KEY) + ); } else if (from_scheme == MULTI_ED25519_SCHEME) { let from_pk = multi_ed25519::new_unvalidated_public_key_from_bytes(from_public_key_bytes); let from_auth_key = multi_ed25519::unvalidated_public_key_to_authentication_key(&from_pk); - assert!(account_resource.authentication_key == from_auth_key, error::unauthenticated(EWRONG_CURRENT_PUBLIC_KEY)); + assert!( + account_resource.authentication_key == from_auth_key, + error::unauthenticated(EWRONG_CURRENT_PUBLIC_KEY) + ); } else { abort error::invalid_argument(EINVALID_SCHEME) }; @@ -354,8 +365,18 @@ module aptos_framework::account { }; // Assert the challenges signed by the current and new keys are valid - assert_valid_rotation_proof_signature_and_get_auth_key(from_scheme, from_public_key_bytes, cap_rotate_key, &challenge); - let new_auth_key = assert_valid_rotation_proof_signature_and_get_auth_key(to_scheme, to_public_key_bytes, cap_update_table, &challenge); + assert_valid_rotation_proof_signature_and_get_auth_key( + from_scheme, + from_public_key_bytes, + cap_rotate_key, + &challenge + ); + let new_auth_key = assert_valid_rotation_proof_signature_and_get_auth_key( + to_scheme, + to_public_key_bytes, + cap_update_table, + &challenge + ); // Update the `OriginatingAddress` table. update_auth_key_and_originating_address_table(addr, account_resource, new_auth_key); @@ -373,7 +394,10 @@ module aptos_framework::account { // Check that there exists a rotation capability offer at the offerer's account resource for the delegate. let delegate_address = signer::address_of(delegate_signer); let offerer_account_resource = borrow_global(rotation_cap_offerer_address); - assert!(option::contains(&offerer_account_resource.rotation_capability_offer.for, &delegate_address), error::not_found(ENO_SUCH_ROTATION_CAPABILITY_OFFER)); + assert!( + option::contains(&offerer_account_resource.rotation_capability_offer.for, &delegate_address), + error::not_found(ENO_SUCH_ROTATION_CAPABILITY_OFFER) + ); let curr_auth_key = from_bcs::to_address(offerer_account_resource.authentication_key); let challenge = RotationProofChallenge { @@ -384,11 +408,20 @@ module aptos_framework::account { }; // Verifies that the `RotationProofChallenge` from above is signed under the new public key that we are rotating to. l - let new_auth_key = assert_valid_rotation_proof_signature_and_get_auth_key(new_scheme, new_public_key_bytes, cap_update_table, &challenge); + let new_auth_key = assert_valid_rotation_proof_signature_and_get_auth_key( + new_scheme, + new_public_key_bytes, + cap_update_table, + &challenge + ); // Update the `OriginatingAddress` table, so we can find the originating address using the new address. let offerer_account_resource = borrow_global_mut(rotation_cap_offerer_address); - update_auth_key_and_originating_address_table(rotation_cap_offerer_address, offerer_account_resource, new_auth_key); + update_auth_key_and_originating_address_table( + rotation_cap_offerer_address, + offerer_account_resource, + new_auth_key + ); } /// Offers rotation capability on behalf of `account` to the account at address `recipient_address`. @@ -431,17 +464,29 @@ module aptos_framework::account { if (account_scheme == ED25519_SCHEME) { let pubkey = ed25519::new_unvalidated_public_key_from_bytes(account_public_key_bytes); let expected_auth_key = ed25519::unvalidated_public_key_to_authentication_key(&pubkey); - assert!(account_resource.authentication_key == expected_auth_key, error::invalid_argument(EWRONG_CURRENT_PUBLIC_KEY)); + assert!( + account_resource.authentication_key == expected_auth_key, + error::invalid_argument(EWRONG_CURRENT_PUBLIC_KEY) + ); let rotation_capability_sig = ed25519::new_signature_from_bytes(rotation_capability_sig_bytes); - assert!(ed25519::signature_verify_strict_t(&rotation_capability_sig, &pubkey, proof_challenge), error::invalid_argument(EINVALID_PROOF_OF_KNOWLEDGE)); + assert!( + ed25519::signature_verify_strict_t(&rotation_capability_sig, &pubkey, proof_challenge), + error::invalid_argument(EINVALID_PROOF_OF_KNOWLEDGE) + ); } else if (account_scheme == MULTI_ED25519_SCHEME) { let pubkey = multi_ed25519::new_unvalidated_public_key_from_bytes(account_public_key_bytes); let expected_auth_key = multi_ed25519::unvalidated_public_key_to_authentication_key(&pubkey); - assert!(account_resource.authentication_key == expected_auth_key, error::invalid_argument(EWRONG_CURRENT_PUBLIC_KEY)); + assert!( + account_resource.authentication_key == expected_auth_key, + error::invalid_argument(EWRONG_CURRENT_PUBLIC_KEY) + ); let rotation_capability_sig = multi_ed25519::new_signature_from_bytes(rotation_capability_sig_bytes); - assert!(multi_ed25519::signature_verify_strict_t(&rotation_capability_sig, &pubkey, proof_challenge), error::invalid_argument(EINVALID_PROOF_OF_KNOWLEDGE)); + assert!( + multi_ed25519::signature_verify_strict_t(&rotation_capability_sig, &pubkey, proof_challenge), + error::invalid_argument(EINVALID_PROOF_OF_KNOWLEDGE) + ); } else { abort error::invalid_argument(EINVALID_SCHEME) }; @@ -473,7 +518,10 @@ module aptos_framework::account { assert!(exists_at(to_be_revoked_address), error::not_found(EACCOUNT_DOES_NOT_EXIST)); let addr = signer::address_of(account); let account_resource = borrow_global_mut(addr); - assert!(option::contains(&account_resource.rotation_capability_offer.for, &to_be_revoked_address), error::not_found(ENO_SUCH_ROTATION_CAPABILITY_OFFER)); + assert!( + option::contains(&account_resource.rotation_capability_offer.for, &to_be_revoked_address), + error::not_found(ENO_SUCH_ROTATION_CAPABILITY_OFFER) + ); revoke_any_rotation_capability(account); } @@ -540,7 +588,10 @@ module aptos_framework::account { assert!(exists_at(to_be_revoked_address), error::not_found(EACCOUNT_DOES_NOT_EXIST)); let addr = signer::address_of(account); let account_resource = borrow_global_mut(addr); - assert!(option::contains(&account_resource.signer_capability_offer.for, &to_be_revoked_address), error::not_found(ENO_SUCH_SIGNER_CAPABILITY)); + assert!( + option::contains(&account_resource.signer_capability_offer.for, &to_be_revoked_address), + error::not_found(ENO_SUCH_SIGNER_CAPABILITY) + ); revoke_any_signer_capability(account); } @@ -558,7 +609,10 @@ module aptos_framework::account { // Check if there's an existing signer capability offer from the offerer. let account_resource = borrow_global(offerer_address); let addr = signer::address_of(account); - assert!(option::contains(&account_resource.signer_capability_offer.for, &addr), error::not_found(ENO_SUCH_SIGNER_CAPABILITY)); + assert!( + option::contains(&account_resource.signer_capability_offer.for, &addr), + error::not_found(ENO_SUCH_SIGNER_CAPABILITY) + ); create_signer(offerer_address) } @@ -566,16 +620,27 @@ module aptos_framework::account { /////////////////////////////////////////////////////////////////////////// /// Helper functions for authentication key rotation. /////////////////////////////////////////////////////////////////////////// - fun assert_valid_rotation_proof_signature_and_get_auth_key(scheme: u8, public_key_bytes: vector, signature: vector, challenge: &RotationProofChallenge): vector { + fun assert_valid_rotation_proof_signature_and_get_auth_key( + scheme: u8, + public_key_bytes: vector, + signature: vector, + challenge: &RotationProofChallenge + ): vector { if (scheme == ED25519_SCHEME) { let pk = ed25519::new_unvalidated_public_key_from_bytes(public_key_bytes); let sig = ed25519::new_signature_from_bytes(signature); - assert!(ed25519::signature_verify_strict_t(&sig, &pk, *challenge), std::error::invalid_argument(EINVALID_PROOF_OF_KNOWLEDGE)); + assert!( + ed25519::signature_verify_strict_t(&sig, &pk, *challenge), + std::error::invalid_argument(EINVALID_PROOF_OF_KNOWLEDGE) + ); ed25519::unvalidated_public_key_to_authentication_key(&pk) } else if (scheme == MULTI_ED25519_SCHEME) { let pk = multi_ed25519::new_unvalidated_public_key_from_bytes(public_key_bytes); let sig = multi_ed25519::new_signature_from_bytes(signature); - assert!(multi_ed25519::signature_verify_strict_t(&sig, &pk, *challenge), std::error::invalid_argument(EINVALID_PROOF_OF_KNOWLEDGE)); + assert!( + multi_ed25519::signature_verify_strict_t(&sig, &pk, *challenge), + std::error::invalid_argument(EINVALID_PROOF_OF_KNOWLEDGE) + ); multi_ed25519::unvalidated_public_key_to_authentication_key(&pk) } else { abort error::invalid_argument(EINVALID_SCHEME) @@ -605,18 +670,23 @@ module aptos_framework::account { // for interoperability because different dapps can implement this in different ways. // If the account with address b calls this function with two valid signatures, it will abort at this step, // because address b is not the account's originating address. - assert!(originating_addr == table::remove(address_map, curr_auth_key), error::not_found(EINVALID_ORIGINATING_ADDRESS)); + assert!( + originating_addr == table::remove(address_map, curr_auth_key), + error::not_found(EINVALID_ORIGINATING_ADDRESS) + ); }; // Set `OriginatingAddress[new_auth_key] = originating_address`. let new_auth_key = from_bcs::to_address(new_auth_key_vector); table::add(address_map, new_auth_key, originating_addr); - event::emit(KeyRotation { - account: originating_addr, - old_authentication_key: account_resource.authentication_key, - new_authentication_key: new_auth_key_vector, - }); + if (std::features::module_event_migration_enabled()) { + event::emit(KeyRotation { + account: originating_addr, + old_authentication_key: account_resource.authentication_key, + new_authentication_key: new_auth_key_vector, + }); + }; event::emit_event( &mut account_resource.key_rotation_events, KeyRotationEvent { @@ -869,8 +939,17 @@ module aptos_framework::account { vector::append(&mut signer_capability_sig_bytes, x"40000000"); // Signers bitmap. let fake_sig = multi_ed25519::new_signature_from_bytes(signer_capability_sig_bytes); - assert!(multi_ed25519::signature_verify_strict_t(&fake_sig, &fake_pk, proof_challenge), error::invalid_state(EINVALID_PROOF_OF_KNOWLEDGE)); - offer_signer_capability(&resource, signer_capability_sig_bytes, MULTI_ED25519_SCHEME, account_public_key_bytes, recipient_address); + assert!( + multi_ed25519::signature_verify_strict_t(&fake_sig, &fake_pk, proof_challenge), + error::invalid_state(EINVALID_PROOF_OF_KNOWLEDGE) + ); + offer_signer_capability( + &resource, + signer_capability_sig_bytes, + MULTI_ED25519_SCHEME, + account_public_key_bytes, + recipient_address + ); } #[test_only] @@ -1038,7 +1117,13 @@ module aptos_framework::account { let alice_signer_capability_offer_sig = ed25519::sign_struct(&alice_sk, challenge); - offer_signer_capability(&alice, ed25519::signature_to_bytes(&alice_signer_capability_offer_sig), 0, alice_pk_bytes, bob_addr); + offer_signer_capability( + &alice, + ed25519::signature_to_bytes(&alice_signer_capability_offer_sig), + 0, + alice_pk_bytes, + bob_addr + ); assert!(option::contains(&borrow_global(alice_addr).signer_capability_offer.for, &bob_addr), 0); @@ -1064,7 +1149,13 @@ module aptos_framework::account { let alice_signer_capability_offer_sig = ed25519::sign_struct(&alice_sk, challenge); - offer_signer_capability(&alice, ed25519::signature_to_bytes(&alice_signer_capability_offer_sig), 0, alice_pk_bytes, bob_addr); + offer_signer_capability( + &alice, + ed25519::signature_to_bytes(&alice_signer_capability_offer_sig), + 0, + alice_pk_bytes, + bob_addr + ); assert!(is_signer_capability_offered(alice_addr), 0); assert!(get_signer_capability_offer_for(alice_addr) == bob_addr, 0); @@ -1073,7 +1164,10 @@ module aptos_framework::account { #[test(bob = @0x345, charlie = @0x567)] #[expected_failure(abort_code = 393230, location = Self)] - public entry fun test_invalid_check_signer_capability_and_create_authorized_signer(bob: signer, charlie: signer) acquires Account { + public entry fun test_invalid_check_signer_capability_and_create_authorized_signer( + bob: signer, + charlie: signer + ) acquires Account { let (alice_sk, alice_pk) = ed25519::generate_keys(); let alice_pk_bytes = ed25519::validated_public_key_to_bytes(&alice_pk); let alice = create_account_from_ed25519_public_key(alice_pk_bytes); @@ -1090,7 +1184,13 @@ module aptos_framework::account { let alice_signer_capability_offer_sig = ed25519::sign_struct(&alice_sk, challenge); - offer_signer_capability(&alice, ed25519::signature_to_bytes(&alice_signer_capability_offer_sig), 0, alice_pk_bytes, bob_addr); + offer_signer_capability( + &alice, + ed25519::signature_to_bytes(&alice_signer_capability_offer_sig), + 0, + alice_pk_bytes, + bob_addr + ); let alice_account_resource = borrow_global_mut(alice_addr); assert!(option::contains(&alice_account_resource.signer_capability_offer.for, &bob_addr), 0); @@ -1116,7 +1216,13 @@ module aptos_framework::account { let alice_signer_capability_offer_sig = ed25519::sign_struct(&alice_sk, challenge); - offer_signer_capability(&alice, ed25519::signature_to_bytes(&alice_signer_capability_offer_sig), 0, alice_pk_bytes, bob_addr); + offer_signer_capability( + &alice, + ed25519::signature_to_bytes(&alice_signer_capability_offer_sig), + 0, + alice_pk_bytes, + bob_addr + ); revoke_signer_capability(&alice, bob_addr); } @@ -1141,7 +1247,13 @@ module aptos_framework::account { recipient_address: bob_addr, }; let alice_signer_capability_offer_sig = ed25519::sign_struct(&alice_sk, challenge); - offer_signer_capability(&alice, ed25519::signature_to_bytes(&alice_signer_capability_offer_sig), 0, alice_pk_bytes, bob_addr); + offer_signer_capability( + &alice, + ed25519::signature_to_bytes(&alice_signer_capability_offer_sig), + 0, + alice_pk_bytes, + bob_addr + ); revoke_signer_capability(&alice, charlie_addr); } @@ -1168,7 +1280,13 @@ module aptos_framework::account { let alice_rotation_capability_offer_sig = ed25519::sign_struct(&alice_sk, challenge); - offer_rotation_capability(&alice, ed25519::signature_to_bytes(&alice_rotation_capability_offer_sig), 0, alice_pk_bytes, bob_addr); + offer_rotation_capability( + &alice, + ed25519::signature_to_bytes(&alice_rotation_capability_offer_sig), + 0, + alice_pk_bytes, + bob_addr + ); let alice_resource = borrow_global_mut(signer::address_of(&alice)); assert!(option::contains(&alice_resource.rotation_capability_offer.for, &bob_addr), 0); @@ -1196,7 +1314,13 @@ module aptos_framework::account { let alice_rotation_capability_offer_sig = ed25519::sign_struct(&alice_sk, challenge); - offer_rotation_capability(&alice, ed25519::signature_to_bytes(&alice_rotation_capability_offer_sig), 0, alice_pk_bytes, signer::address_of(&bob)); + offer_rotation_capability( + &alice, + ed25519::signature_to_bytes(&alice_rotation_capability_offer_sig), + 0, + alice_pk_bytes, + signer::address_of(&bob) + ); } #[test(bob = @0x345, framework = @aptos_framework)] @@ -1219,13 +1343,23 @@ module aptos_framework::account { let alice_rotation_capability_offer_sig = ed25519::sign_struct(&alice_sk, challenge); - offer_rotation_capability(&alice, ed25519::signature_to_bytes(&alice_rotation_capability_offer_sig), 0, alice_pk_bytes, signer::address_of(&bob)); + offer_rotation_capability( + &alice, + ed25519::signature_to_bytes(&alice_rotation_capability_offer_sig), + 0, + alice_pk_bytes, + signer::address_of(&bob) + ); revoke_rotation_capability(&alice, signer::address_of(&bob)); } #[test(bob = @0x345, charlie = @0x567, framework = @aptos_framework)] #[expected_failure(abort_code = 393234, location = Self)] - public entry fun test_invalid_revoke_rotation_capability(bob: signer, charlie: signer, framework: signer) acquires Account { + public entry fun test_invalid_revoke_rotation_capability( + bob: signer, + charlie: signer, + framework: signer + ) acquires Account { chain_id::initialize_for_test(&framework, 4); let (alice_sk, alice_pk) = ed25519::generate_keys(); let alice_pk_bytes = ed25519::validated_public_key_to_bytes(&alice_pk); @@ -1245,7 +1379,13 @@ module aptos_framework::account { let alice_rotation_capability_offer_sig = ed25519::sign_struct(&alice_sk, challenge); - offer_rotation_capability(&alice, ed25519::signature_to_bytes(&alice_rotation_capability_offer_sig), 0, alice_pk_bytes, signer::address_of(&bob)); + offer_rotation_capability( + &alice, + ed25519::signature_to_bytes(&alice_rotation_capability_offer_sig), + 0, + alice_pk_bytes, + signer::address_of(&bob) + ); revoke_rotation_capability(&alice, signer::address_of(&charlie)); } @@ -1254,7 +1394,9 @@ module aptos_framework::account { // #[test(account = @aptos_framework)] - public entry fun test_valid_rotate_authentication_key_multi_ed25519_to_multi_ed25519(account: signer) acquires Account, OriginatingAddress { + public entry fun test_valid_rotate_authentication_key_multi_ed25519_to_multi_ed25519( + account: signer + ) acquires Account, OriginatingAddress { initialize(&account); let (curr_sk, curr_pk) = multi_ed25519::generate_keys(2, 3); let curr_pk_unvalidated = multi_ed25519::public_key_to_unvalidated(&curr_pk); @@ -1293,7 +1435,9 @@ module aptos_framework::account { } #[test(account = @aptos_framework)] - public entry fun test_valid_rotate_authentication_key_multi_ed25519_to_ed25519(account: signer) acquires Account, OriginatingAddress { + public entry fun test_valid_rotate_authentication_key_multi_ed25519_to_ed25519( + account: signer + ) acquires Account, OriginatingAddress { initialize(&account); let (curr_sk, curr_pk) = multi_ed25519::generate_keys(2, 3); @@ -1364,9 +1508,10 @@ module aptos_framework::account { } #[test_only] - struct FakeCoin { } + struct FakeCoin {} + #[test_only] - struct SadFakeCoin { } + struct SadFakeCoin {} #[test(account = @0x1234)] fun test_events(account: &signer) acquires Account { diff --git a/aptos-move/framework/aptos-framework/sources/aptos_account.move b/aptos-move/framework/aptos-framework/sources/aptos_account.move index d1ac5e13ac905..1d5c1fda7f6ec 100644 --- a/aptos-move/framework/aptos-framework/sources/aptos_account.move +++ b/aptos-move/framework/aptos-framework/sources/aptos_account.move @@ -36,7 +36,7 @@ module aptos_framework::aptos_account { } #[event] - struct AllowDirectTransfers has drop, store { + struct DirectCoinTransferConfigUpdated has drop, store { account: address, new_allow_direct_transfers: bool, } @@ -140,8 +140,10 @@ module aptos_framework::aptos_account { }; direct_transfer_config.allow_arbitrary_coin_transfers = allow; - emit( - AllowDirectTransfers { account: addr, new_allow_direct_transfers: allow }); + + if (std::features::module_event_migration_enabled()) { + emit(DirectCoinTransferConfigUpdated { account: addr, new_allow_direct_transfers: allow }); + }; emit_event( &mut direct_transfer_config.update_coin_transfer_events, DirectCoinTransferConfigUpdatedEvent { new_allow_direct_transfers: allow }); @@ -150,8 +152,9 @@ module aptos_framework::aptos_account { allow_arbitrary_coin_transfers: allow, update_coin_transfer_events: new_event_handle(account), }; - emit( - AllowDirectTransfers { account: addr, new_allow_direct_transfers: allow }); + if (std::features::module_event_migration_enabled()) { + emit(DirectCoinTransferConfigUpdated { account: addr, new_allow_direct_transfers: allow }); + }; emit_event( &mut direct_transfer_config.update_coin_transfer_events, DirectCoinTransferConfigUpdatedEvent { new_allow_direct_transfers: allow }); diff --git a/aptos-move/framework/aptos-framework/sources/aptos_governance.move b/aptos-move/framework/aptos-framework/sources/aptos_governance.move index b0477ffa41924..e6826633c556c 100644 --- a/aptos-move/framework/aptos-framework/sources/aptos_governance.move +++ b/aptos-move/framework/aptos-framework/sources/aptos_governance.move @@ -138,6 +138,34 @@ module aptos_framework::aptos_governance { voting_duration_secs: u64, } + #[event] + /// Event emitted when a proposal is created. + struct CreateProposal has drop, store { + proposer: address, + stake_pool: address, + proposal_id: u64, + execution_hash: vector, + proposal_metadata: SimpleMap>, + } + + #[event] + /// Event emitted when there's a vote on a proposa; + struct Vote has drop, store { + proposal_id: u64, + voter: address, + stake_pool: address, + num_votes: u64, + should_pass: bool, + } + + #[event] + /// Event emitted when the governance configs are updated. + struct UpdateConfig has drop, store { + min_voting_threshold: u128, + required_proposer_stake: u64, + voting_duration_secs: u64, + } + /// Can be called during genesis or by the governance itself. /// Stores the signer capability for a given address. public fun store_signer_cap( @@ -149,7 +177,10 @@ module aptos_framework::aptos_governance { system_addresses::assert_framework_reserved(signer_address); if (!exists(@aptos_framework)) { - move_to(aptos_framework, GovernanceResponsbility { signer_caps: simple_map::create() }); + move_to( + aptos_framework, + GovernanceResponsbility { signer_caps: simple_map::create() } + ); }; let signer_caps = &mut borrow_global_mut(@aptos_framework).signer_caps; @@ -201,6 +232,15 @@ module aptos_framework::aptos_governance { governance_config.min_voting_threshold = min_voting_threshold; governance_config.required_proposer_stake = required_proposer_stake; + if (std::features::module_event_migration_enabled()) { + event::emit( + UpdateConfig { + min_voting_threshold, + required_proposer_stake, + voting_duration_secs + }, + ) + }; let events = borrow_global_mut(@aptos_framework); event::emit_event( &mut events.update_config_events, @@ -255,10 +295,16 @@ module aptos_framework::aptos_governance { #[view] /// Return remaining voting power of a stake pool on a proposal. /// Note: a stake pool's voting power on a proposal could increase over time(e.g. rewards/new stake). - public fun get_remaining_voting_power(stake_pool: address, proposal_id: u64): u64 acquires VotingRecords, VotingRecordsV2 { + public fun get_remaining_voting_power( + stake_pool: address, + proposal_id: u64 + ): u64 acquires VotingRecords, VotingRecordsV2 { assert_voting_initialization(); - let proposal_expiration = voting::get_proposal_expiration_secs(@aptos_framework, proposal_id); + let proposal_expiration = voting::get_proposal_expiration_secs( + @aptos_framework, + proposal_id + ); let lockup_until = stake::get_lockup_secs(stake_pool); // The voter's stake needs to be locked up at least as long as the proposal's expiration. // Also no one can vote on a expired proposal. @@ -307,7 +353,14 @@ module aptos_framework::aptos_governance { metadata_hash: vector, is_multi_step_proposal: bool, ) acquires GovernanceConfig, GovernanceEvents { - create_proposal_v2_impl(proposer, stake_pool, execution_hash, metadata_location, metadata_hash, is_multi_step_proposal); + create_proposal_v2_impl( + proposer, + stake_pool, + execution_hash, + metadata_location, + metadata_hash, + is_multi_step_proposal + ); } /// Create a single-step or multi-step proposal with the backing `stake_pool`. @@ -323,7 +376,10 @@ module aptos_framework::aptos_governance { is_multi_step_proposal: bool, ): u64 acquires GovernanceConfig, GovernanceEvents { let proposer_address = signer::address_of(proposer); - assert!(stake::get_delegated_voter(stake_pool) == proposer_address, error::invalid_argument(ENOT_DELEGATED_VOTER)); + assert!( + stake::get_delegated_voter(stake_pool) == proposer_address, + error::invalid_argument(ENOT_DELEGATED_VOTER) + ); // The proposer's stake needs to be at least the required bond amount. let governance_config = borrow_global(@aptos_framework); @@ -368,6 +424,17 @@ module aptos_framework::aptos_governance { is_multi_step_proposal, ); + if (std::features::module_event_migration_enabled()) { + event::emit( + CreateProposal { + proposal_id, + proposer: proposer_address, + stake_pool, + execution_hash, + proposal_metadata, + }, + ); + }; let events = borrow_global_mut(@aptos_framework); event::emit_event( &mut events.create_proposal_events, @@ -388,7 +455,7 @@ module aptos_framework::aptos_governance { stake_pool: address, proposal_id: u64, should_pass: bool, - ) acquires ApprovedExecutionHashes, GovernanceEvents, VotingRecords, VotingRecordsV2 { + ) acquires ApprovedExecutionHashes, VotingRecords, VotingRecordsV2, GovernanceEvents { vote_internal(voter, stake_pool, proposal_id, MAX_U64, should_pass); } @@ -399,7 +466,7 @@ module aptos_framework::aptos_governance { proposal_id: u64, voting_power: u64, should_pass: bool, - ) acquires ApprovedExecutionHashes, GovernanceEvents, VotingRecords, VotingRecordsV2 { + ) acquires ApprovedExecutionHashes, VotingRecords, VotingRecordsV2, GovernanceEvents { vote_internal(voter, stake_pool, proposal_id, voting_power, should_pass); } @@ -413,12 +480,15 @@ module aptos_framework::aptos_governance { proposal_id: u64, voting_power: u64, should_pass: bool, - ) acquires ApprovedExecutionHashes, GovernanceEvents, VotingRecords, VotingRecordsV2 { + ) acquires ApprovedExecutionHashes, VotingRecords, VotingRecordsV2, GovernanceEvents { let voter_address = signer::address_of(voter); assert!(stake::get_delegated_voter(stake_pool) == voter_address, error::invalid_argument(ENOT_DELEGATED_VOTER)); // The voter's stake needs to be locked up at least as long as the proposal's expiration. - let proposal_expiration = voting::get_proposal_expiration_secs(@aptos_framework, proposal_id); + let proposal_expiration = voting::get_proposal_expiration_secs( + @aptos_framework, + proposal_id + ); assert!( stake::get_lockup_secs(stake_pool) >= proposal_expiration, error::invalid_argument(EINSUFFICIENT_STAKE_LOCKUP), @@ -427,7 +497,7 @@ module aptos_framework::aptos_governance { // If a stake pool has already voted on a proposal before partial governance voting is enabled, // `get_remaining_voting_power` returns 0. let staking_pool_voting_power = get_remaining_voting_power(stake_pool, proposal_id); - voting_power= min(voting_power, staking_pool_voting_power); + voting_power = min(voting_power, staking_pool_voting_power); // Short-circuit if the voter has no voting power. assert!(voting_power > 0, error::invalid_argument(ENO_VOTING_POWER)); @@ -457,6 +527,17 @@ module aptos_framework::aptos_governance { table::add(&mut voting_records.votes, record_key, true); }; + if (std::features::module_event_migration_enabled()) { + event::emit( + Vote { + proposal_id, + voter: voter_address, + stake_pool, + num_votes: voting_power, + should_pass, + }, + ); + }; let events = borrow_global_mut(@aptos_framework); event::emit_event( &mut events.vote_events, @@ -503,14 +584,21 @@ module aptos_framework::aptos_governance { /// Resolve a successful single-step proposal. This would fail if the proposal is not successful (not enough votes or more no /// than yes). - public fun resolve(proposal_id: u64, signer_address: address): signer acquires ApprovedExecutionHashes, GovernanceResponsbility { + public fun resolve( + proposal_id: u64, + signer_address: address + ): signer acquires ApprovedExecutionHashes, GovernanceResponsbility { voting::resolve(@aptos_framework, proposal_id); remove_approved_hash(proposal_id); get_signer(signer_address) } /// Resolve a successful multi-step proposal. This would fail if the proposal is not successful. - public fun resolve_multi_step_proposal(proposal_id: u64, signer_address: address, next_execution_hash: vector): signer acquires GovernanceResponsbility, ApprovedExecutionHashes { + public fun resolve_multi_step_proposal( + proposal_id: u64, + signer_address: address, + next_execution_hash: vector + ): signer acquires GovernanceResponsbility, ApprovedExecutionHashes { voting::resolve_proposal_v2(@aptos_framework, proposal_id, next_execution_hash); // If the current step is the last step of this multi-step proposal, // we will remove the execution hash from the ApprovedExecutionHashes map. @@ -613,7 +701,10 @@ module aptos_framework::aptos_governance { create_signer_with_capability(signer_cap) } - fun create_proposal_metadata(metadata_location: vector, metadata_hash: vector): SimpleMap> { + fun create_proposal_metadata( + metadata_location: vector, + metadata_hash: vector + ): SimpleMap> { assert!(string::length(&utf8(metadata_location)) <= 256, error::invalid_argument(EMETADATA_LOCATION_TOO_LONG)); assert!(string::length(&utf8(metadata_hash)) <= 256, error::invalid_argument(EMETADATA_HASH_TOO_LONG)); @@ -657,7 +748,12 @@ module aptos_framework::aptos_governance { } #[test_only] - public fun resolve_proposal_for_test(proposal_id: u64, signer_address: address, multi_step: bool, finish_multi_step_execution: bool): signer acquires ApprovedExecutionHashes, GovernanceResponsbility { + public fun resolve_proposal_for_test( + proposal_id: u64, + signer_address: address, + multi_step: bool, + finish_multi_step_execution: bool + ): signer acquires ApprovedExecutionHashes, GovernanceResponsbility { if (multi_step) { let execution_hash = vector::empty(); vector::push_back(&mut execution_hash, 1); @@ -686,7 +782,7 @@ module aptos_framework::aptos_governance { no_voter: signer, multi_step: bool, use_generic_resolve_function: bool, - ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceEvents, GovernanceResponsbility, VotingRecords, VotingRecordsV2 { + ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceResponsbility, VotingRecords, VotingRecordsV2, GovernanceEvents { setup_voting(&aptos_framework, &proposer, &yes_voter, &no_voter); let execution_hash = vector::empty(); @@ -731,7 +827,7 @@ module aptos_framework::aptos_governance { proposer: signer, yes_voter: signer, no_voter: signer, - ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceEvents, GovernanceResponsbility, VotingRecords, VotingRecordsV2 { + ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceResponsbility, VotingRecords, VotingRecordsV2, GovernanceEvents { test_voting_generic(aptos_framework, proposer, yes_voter, no_voter, false, false); } @@ -741,18 +837,18 @@ module aptos_framework::aptos_governance { proposer: signer, yes_voter: signer, no_voter: signer, - ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceEvents, GovernanceResponsbility, VotingRecords, VotingRecordsV2 { + ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceResponsbility, VotingRecords, VotingRecordsV2, GovernanceEvents { test_voting_generic(aptos_framework, proposer, yes_voter, no_voter, true, true); } #[test(aptos_framework = @aptos_framework, proposer = @0x123, yes_voter = @0x234, no_voter = @345)] - #[expected_failure(abort_code=0x5000a, location = aptos_framework::voting)] + #[expected_failure(abort_code = 0x5000a, location = aptos_framework::voting)] public entry fun test_voting_multi_step_cannot_use_single_step_resolve( aptos_framework: signer, proposer: signer, yes_voter: signer, no_voter: signer, - ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceEvents, GovernanceResponsbility, VotingRecords, VotingRecordsV2 { + ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceResponsbility, VotingRecords, VotingRecordsV2, GovernanceEvents { test_voting_generic(aptos_framework, proposer, yes_voter, no_voter, true, false); } @@ -762,7 +858,7 @@ module aptos_framework::aptos_governance { proposer: signer, yes_voter: signer, no_voter: signer, - ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceEvents, GovernanceResponsbility, VotingRecords, VotingRecordsV2 { + ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceResponsbility, VotingRecords, VotingRecordsV2, GovernanceEvents { test_voting_generic(aptos_framework, proposer, yes_voter, no_voter, false, true); } @@ -773,7 +869,7 @@ module aptos_framework::aptos_governance { yes_voter: signer, no_voter: signer, multi_step: bool, - ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceEvents, GovernanceResponsbility, VotingRecords, VotingRecordsV2 { + ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceResponsbility, VotingRecords, VotingRecordsV2, GovernanceEvents { setup_voting(&aptos_framework, &proposer, &yes_voter, &no_voter); create_proposal_for_test(&proposer, multi_step); @@ -811,8 +907,14 @@ module aptos_framework::aptos_governance { proposer: signer, yes_voter: signer, no_voter: signer, - ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceEvents, GovernanceResponsbility, VotingRecords, VotingRecordsV2 { - test_can_remove_approved_hash_if_executed_directly_via_voting_generic(aptos_framework, proposer, yes_voter, no_voter, false); + ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceResponsbility, VotingRecords, VotingRecordsV2, GovernanceEvents { + test_can_remove_approved_hash_if_executed_directly_via_voting_generic( + aptos_framework, + proposer, + yes_voter, + no_voter, + false + ); } #[test(aptos_framework = @aptos_framework, proposer = @0x123, yes_voter = @0x234, no_voter = @345)] @@ -821,8 +923,14 @@ module aptos_framework::aptos_governance { proposer: signer, yes_voter: signer, no_voter: signer, - ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceEvents, GovernanceResponsbility, VotingRecords, VotingRecordsV2 { - test_can_remove_approved_hash_if_executed_directly_via_voting_generic(aptos_framework, proposer, yes_voter, no_voter, true); + ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceResponsbility, VotingRecords, VotingRecordsV2, GovernanceEvents { + test_can_remove_approved_hash_if_executed_directly_via_voting_generic( + aptos_framework, + proposer, + yes_voter, + no_voter, + true + ); } #[test(aptos_framework = @aptos_framework, proposer = @0x123, voter_1 = @0x234, voter_2 = @345)] @@ -832,7 +940,7 @@ module aptos_framework::aptos_governance { proposer: signer, voter_1: signer, voter_2: signer, - ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceEvents, GovernanceResponsbility, VotingRecords, VotingRecordsV2 { + ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceResponsbility, VotingRecords, VotingRecordsV2, GovernanceEvents { setup_voting(&aptos_framework, &proposer, &voter_1, &voter_2); create_proposal( @@ -855,7 +963,7 @@ module aptos_framework::aptos_governance { proposer: signer, voter_1: signer, voter_2: signer, - ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceEvents, GovernanceResponsbility, VotingRecords, VotingRecordsV2 { + ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceResponsbility, VotingRecords, VotingRecordsV2, GovernanceEvents { setup_voting(&aptos_framework, &proposer, &voter_1, &voter_2); create_proposal( @@ -878,7 +986,7 @@ module aptos_framework::aptos_governance { proposer: signer, voter_1: signer, voter_2: signer, - ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceEvents, GovernanceResponsbility, VotingRecords, VotingRecordsV2 { + ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceResponsbility, VotingRecords, VotingRecordsV2, GovernanceEvents { setup_partial_voting(&aptos_framework, &proposer, &voter_1, &voter_2); let execution_hash = vector::empty(); vector::push_back(&mut execution_hash, 1); @@ -906,7 +1014,7 @@ module aptos_framework::aptos_governance { proposer: signer, voter_1: signer, voter_2: signer, - ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceEvents, GovernanceResponsbility, VotingRecords, VotingRecordsV2 { + ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceResponsbility, VotingRecords, VotingRecordsV2, GovernanceEvents { setup_partial_voting(&aptos_framework, &proposer, &voter_1, &voter_2); let execution_hash = vector::empty(); vector::push_back(&mut execution_hash, 1); @@ -932,7 +1040,7 @@ module aptos_framework::aptos_governance { proposer: signer, voter_1: signer, voter_2: signer, - ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceEvents, GovernanceResponsbility, VotingRecords, VotingRecordsV2 { + ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceResponsbility, VotingRecords, VotingRecordsV2, GovernanceEvents { setup_partial_voting(&aptos_framework, &proposer, &voter_1, &voter_2); let execution_hash = vector::empty(); vector::push_back(&mut execution_hash, 1); @@ -959,7 +1067,7 @@ module aptos_framework::aptos_governance { proposer: signer, voter_1: signer, voter_2: signer, - ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceEvents, GovernanceResponsbility, VotingRecords, VotingRecordsV2 { + ) acquires ApprovedExecutionHashes, GovernanceConfig, GovernanceResponsbility, VotingRecords, VotingRecordsV2, GovernanceEvents { setup_voting(&aptos_framework, &proposer, &voter_1, &voter_2); let execution_hash = vector::empty(); vector::push_back(&mut execution_hash, 1); @@ -996,7 +1104,7 @@ module aptos_framework::aptos_governance { proposer: signer, voter_1: signer, voter_2: signer, - ) acquires GovernanceConfig, GovernanceEvents, GovernanceResponsbility, VotingRecords, VotingRecordsV2 { + ) acquires GovernanceConfig, GovernanceResponsbility, VotingRecords, VotingRecordsV2, GovernanceEvents { setup_voting_with_initialized_stake(&aptos_framework, &proposer, &voter_1, &voter_2); let execution_hash = vector::empty(); vector::push_back(&mut execution_hash, 1); @@ -1165,7 +1273,7 @@ module aptos_framework::aptos_governance { proposer: signer, yes_voter: signer, no_voter: signer, - ) acquires GovernanceResponsbility, GovernanceConfig, GovernanceEvents, ApprovedExecutionHashes, VotingRecords, VotingRecordsV2 { + ) acquires GovernanceResponsbility, GovernanceConfig, ApprovedExecutionHashes, VotingRecords, VotingRecordsV2, GovernanceEvents { setup_voting(&aptos_framework, &proposer, &yes_voter, &no_voter); create_proposal_for_test(&proposer, true); @@ -1191,7 +1299,7 @@ module aptos_framework::aptos_governance { }; let approved_hashes = borrow_global(@aptos_framework).hashes; - assert!(*simple_map::borrow(&approved_hashes, &0) == vector[10u8,], 1); + assert!(*simple_map::borrow(&approved_hashes, &0) == vector[10u8, ], 1); } #[test_only] diff --git a/aptos-move/framework/aptos-framework/sources/block.move b/aptos-move/framework/aptos-framework/sources/block.move index 4c485a5a7d6a3..5899481316be7 100644 --- a/aptos-move/framework/aptos-framework/sources/block.move +++ b/aptos-move/framework/aptos-framework/sources/block.move @@ -59,6 +59,27 @@ module aptos_framework::block { new_epoch_interval: u64, } + #[event] + /// Should be in-sync with NewBlockEvent rust struct in new_block.rs + struct NewBlock has drop, store { + hash: address, + epoch: u64, + round: u64, + height: u64, + previous_block_votes_bitvec: vector, + proposer: address, + failed_proposer_indices: vector, + /// On-chain time during the block at the given height + time_microseconds: u64, + } + + #[event] + /// Event emitted when a proposal is created. + struct UpdateEpochInterval has drop, store { + old_epoch_interval: u64, + new_epoch_interval: u64, + } + /// The number of new block events does not equal the current block height. const ENUM_NEW_BLOCK_EVENTS_DOES_NOT_MATCH_BLOCK_HEIGHT: u64 = 1; /// An invalid proposer was provided. Expected the proposer to be the VM or an active validator. @@ -113,6 +134,11 @@ module aptos_framework::block { let old_epoch_interval = block_resource.epoch_interval; block_resource.epoch_interval = new_epoch_interval; + if (std::features::module_event_migration_enabled()) { + event::emit( + UpdateEpochInterval { old_epoch_interval, new_epoch_interval }, + ); + }; event::emit_event( &mut block_resource.update_epoch_interval_events, UpdateEpochIntervalEvent { old_epoch_interval, new_epoch_interval }, @@ -153,6 +179,7 @@ module aptos_framework::block { let block_metadata_ref = borrow_global_mut(@aptos_framework); block_metadata_ref.height = event::counter(&block_metadata_ref.new_block_events); + // Emit both event v1 and v2 for compatibility. Eventually only module events will be kept. let new_block_event = NewBlockEvent { hash, epoch, @@ -163,7 +190,17 @@ module aptos_framework::block { failed_proposer_indices, time_microseconds: timestamp, }; - emit_new_block_event(vm, &mut block_metadata_ref.new_block_events, new_block_event); + let new_block_event_v2 = NewBlock { + hash, + epoch, + round, + height: block_metadata_ref.height, + previous_block_votes_bitvec, + proposer, + failed_proposer_indices, + time_microseconds: timestamp, + }; + emit_new_block_event(vm, &mut block_metadata_ref.new_block_events, new_block_event, new_block_event_v2); if (features::collect_and_distribute_gas_fees()) { // Assign the fees collected from the previous block to the previous block proposer. @@ -237,7 +274,12 @@ module aptos_framework::block { } /// Emit the event and update height and global timestamp - fun emit_new_block_event(vm: &signer, event_handle: &mut EventHandle, new_block_event: NewBlockEvent) acquires CommitHistory { + fun emit_new_block_event( + vm: &signer, + event_handle: &mut EventHandle, + new_block_event: NewBlockEvent, + new_block_event_v2: NewBlock + ) acquires CommitHistory { if (exists(@aptos_framework)) { let commit_history_ref = borrow_global_mut(@aptos_framework); let idx = commit_history_ref.next_idx; @@ -255,6 +297,9 @@ module aptos_framework::block { event::counter(event_handle) == new_block_event.height, error::invalid_argument(ENUM_NEW_BLOCK_EVENTS_DOES_NOT_MATCH_BLOCK_HEIGHT), ); + if (std::features::module_event_migration_enabled()) { + event::emit(new_block_event_v2); + }; event::emit_event(event_handle, new_block_event); } @@ -275,6 +320,16 @@ module aptos_framework::block { proposer: @vm_reserved, failed_proposer_indices: vector::empty(), time_microseconds: 0, + }, + NewBlock { + hash: genesis_id, + epoch: 0, + round: 0, + height: 0, + previous_block_votes_bitvec: vector::empty(), + proposer: @vm_reserved, + failed_proposer_indices: vector::empty(), + time_microseconds: 0, } ); } @@ -298,6 +353,16 @@ module aptos_framework::block { proposer: @vm_reserved, failed_proposer_indices: vector::empty(), time_microseconds: timestamp::now_microseconds(), + }, + NewBlock { + hash: fake_block_hash, + epoch: reconfiguration::current_epoch(), + round: MAX_U64, + height: block_metadata_ref.height, + previous_block_votes_bitvec: vector::empty(), + proposer: @vm_reserved, + failed_proposer_indices: vector::empty(), + time_microseconds: timestamp::now_microseconds(), } ); } diff --git a/aptos-move/framework/aptos-framework/sources/coin.move b/aptos-move/framework/aptos-framework/sources/coin.move index 18259efba865f..2e7a9aa6a4a0b 100644 --- a/aptos-move/framework/aptos-framework/sources/coin.move +++ b/aptos-move/framework/aptos-framework/sources/coin.move @@ -371,11 +371,13 @@ module aptos_framework::coin { !coin_store.frozen, error::permission_denied(EFROZEN), ); + if (std::features::module_event_migration_enabled()) { + event::emit(Deposit { account: account_addr, amount: coin.value }); + }; event::emit_event( &mut coin_store.deposit_events, DepositEvent { amount: coin.value }, ); - event::emit(Deposit { account: account_addr, amount: coin.value }); merge(&mut coin_store.coin, coin); } @@ -640,11 +642,13 @@ module aptos_framework::coin { error::permission_denied(EFROZEN), ); + if (std::features::module_event_migration_enabled()) { + event::emit(Withdraw { account: account_addr, amount }); + }; event::emit_event( &mut coin_store.withdraw_events, WithdrawEvent { amount }, ); - event::emit(Withdraw { account: account_addr, amount }); extract(&mut coin_store.coin, amount) } diff --git a/aptos-move/framework/aptos-framework/sources/fungible_asset.move b/aptos-move/framework/aptos-framework/sources/fungible_asset.move index 12ba05fcd4b93..efe0351196a4a 100644 --- a/aptos-move/framework/aptos-framework/sources/fungible_asset.move +++ b/aptos-move/framework/aptos-framework/sources/fungible_asset.move @@ -542,7 +542,7 @@ module aptos_framework::fungible_asset { let store = borrow_global_mut(store_addr); store.balance = store.balance + amount; - event::emit(Deposit { store: store_addr, amount }); + event::emit(Deposit { store: store_addr, amount }); } /// Extract `amount` of the fungible asset from `store`. @@ -556,7 +556,7 @@ module aptos_framework::fungible_asset { store.balance = store.balance - amount; let metadata = store.metadata; - event::emit(Withdraw { store: store_addr, amount }); + event::emit(Withdraw { store: store_addr, amount }); FungibleAsset { metadata, amount } } diff --git a/aptos-move/framework/aptos-framework/sources/multisig_account.move b/aptos-move/framework/aptos-framework/sources/multisig_account.move index f973f8c4fb566..4114a111a19a6 100644 --- a/aptos-move/framework/aptos-framework/sources/multisig_account.move +++ b/aptos-move/framework/aptos-framework/sources/multisig_account.move @@ -41,7 +41,7 @@ module aptos_framework::multisig_account { use aptos_framework::chain_id; use aptos_framework::create_signer::create_signer; use aptos_framework::coin; - use aptos_framework::event::{EventHandle, emit_event}; + use aptos_framework::event::{EventHandle, emit_event, emit}; use aptos_framework::timestamp::now_seconds; use aptos_std::simple_map::{Self, SimpleMap}; use aptos_std::table::{Self, Table}; @@ -204,17 +204,36 @@ module aptos_framework::multisig_account { owners_added: vector
, } + #[event] + struct AddOwners has drop, store { + multisig_account: address, + owners_added: vector
, + } + /// Event emitted when new owners are removed from the multisig account. struct RemoveOwnersEvent has drop, store { owners_removed: vector
, } + #[event] + struct RemoveOwners has drop, store { + multisig_account: address, + owners_removed: vector
, + } + /// Event emitted when the number of signatures required is updated. struct UpdateSignaturesRequiredEvent has drop, store { old_num_signatures_required: u64, new_num_signatures_required: u64, } + #[event] + struct UpdateSignaturesRequired has drop, store { + multisig_account: address, + old_num_signatures_required: u64, + new_num_signatures_required: u64, + } + /// Event emitted when a transaction is created. struct CreateTransactionEvent has drop, store { creator: address, @@ -222,6 +241,14 @@ module aptos_framework::multisig_account { transaction: MultisigTransaction, } + #[event] + struct CreateTransaction has drop, store { + multisig_account: address, + creator: address, + sequence_number: u64, + transaction: MultisigTransaction, + } + /// Event emitted when an owner approves or rejects a transaction. struct VoteEvent has drop, store { owner: address, @@ -229,6 +256,14 @@ module aptos_framework::multisig_account { approved: bool, } + #[event] + struct Vote has drop, store { + multisig_account: address, + owner: address, + sequence_number: u64, + approved: bool, + } + /// Event emitted when a transaction is officially rejected because the number of rejections has reached the /// number of signatures required. struct ExecuteRejectedTransactionEvent has drop, store { @@ -237,6 +272,14 @@ module aptos_framework::multisig_account { executor: address, } + #[event] + struct ExecuteRejectedTransaction has drop, store { + multisig_account: address, + sequence_number: u64, + num_rejections: u64, + executor: address, + } + /// Event emitted when a transaction is executed. struct TransactionExecutionSucceededEvent has drop, store { executor: address, @@ -245,6 +288,15 @@ module aptos_framework::multisig_account { num_approvals: u64, } + #[event] + struct TransactionExecutionSucceeded has drop, store { + multisig_account: address, + executor: address, + sequence_number: u64, + transaction_payload: vector, + num_approvals: u64, + } + /// Event emitted when a transaction's execution failed. struct TransactionExecutionFailedEvent has drop, store { executor: address, @@ -254,12 +306,29 @@ module aptos_framework::multisig_account { execution_error: ExecutionError, } + #[event] + struct TransactionExecutionFailed has drop, store { + multisig_account: address, + executor: address, + sequence_number: u64, + transaction_payload: vector, + num_approvals: u64, + execution_error: ExecutionError, + } + /// Event emitted when a transaction's metadata is updated. struct MetadataUpdatedEvent has drop, store { old_metadata: SimpleMap>, new_metadata: SimpleMap>, } + #[event] + struct MetadataUpdated has drop, store { + multisig_account: address, + old_metadata: SimpleMap>, + new_metadata: SimpleMap>, + } + ////////////////////////// View functions /////////////////////////////// #[view] @@ -303,7 +372,9 @@ module aptos_framework::multisig_account { #[view] /// Return all pending transactions. - public fun get_pending_transactions(multisig_account: address): vector acquires MultisigAccount { + public fun get_pending_transactions( + multisig_account: address + ): vector acquires MultisigAccount { let pending_transactions: vector = vector[]; let multisig_account = borrow_global(multisig_account); let i = multisig_account.last_executed_sequence_number + 1; @@ -796,6 +867,15 @@ module aptos_framework::multisig_account { }; if (emit_event) { + if (std::features::module_event_migration_enabled()) { + emit( + MetadataUpdated { + multisig_account: multisig_address, + old_metadata, + new_metadata: multisig_account_resource.metadata, + } + ) + }; emit_event( &mut multisig_account_resource.metadata_updated_events, MetadataUpdatedEvent { @@ -828,7 +908,7 @@ module aptos_framework::multisig_account { creator, creation_time_secs: now_seconds(), }; - add_transaction(creator, multisig_account_resource, transaction); + add_transaction(creator, multisig_account, multisig_account_resource, transaction); } /// Create a multisig transaction with a transaction hash instead of the full payload. @@ -854,7 +934,7 @@ module aptos_framework::multisig_account { creator, creation_time_secs: now_seconds(), }; - add_transaction(creator, multisig_account_resource, transaction); + add_transaction(creator, multisig_account, multisig_account_resource, transaction); } /// Approve a multisig transaction. @@ -892,6 +972,16 @@ module aptos_framework::multisig_account { simple_map::add(votes, owner_addr, approved); }; + if (std::features::module_event_migration_enabled()) { + emit( + Vote { + multisig_account, + owner: owner_addr, + sequence_number, + approved, + } + ); + }; emit_event( &mut multisig_account_resource.vote_events, VoteEvent { @@ -943,6 +1033,16 @@ module aptos_framework::multisig_account { error::invalid_state(ENOT_ENOUGH_REJECTIONS), ); + if (std::features::module_event_migration_enabled()) { + emit( + ExecuteRejectedTransaction { + multisig_account, + sequence_number, + num_rejections, + executor: address_of(owner), + } + ); + }; emit_event( &mut multisig_account_resource.execute_rejected_transaction_events, ExecuteRejectedTransactionEvent { @@ -1015,6 +1115,17 @@ module aptos_framework::multisig_account { ) acquires MultisigAccount { let num_approvals = transaction_execution_cleanup_common(executor, multisig_account); let multisig_account_resource = borrow_global_mut(multisig_account); + if (std::features::module_event_migration_enabled()) { + emit( + TransactionExecutionSucceeded { + multisig_account, + sequence_number: multisig_account_resource.last_executed_sequence_number, + transaction_payload, + num_approvals, + executor, + } + ); + }; emit_event( &mut multisig_account_resource.execute_transaction_events, TransactionExecutionSucceededEvent { @@ -1036,6 +1147,18 @@ module aptos_framework::multisig_account { ) acquires MultisigAccount { let num_approvals = transaction_execution_cleanup_common(executor, multisig_account); let multisig_account_resource = borrow_global_mut(multisig_account); + if (std::features::module_event_migration_enabled()) { + emit( + TransactionExecutionFailed { + multisig_account, + executor, + sequence_number: multisig_account_resource.last_executed_sequence_number, + transaction_payload, + num_approvals, + execution_error, + } + ); + }; emit_event( &mut multisig_account_resource.transaction_execution_failed_events, TransactionExecutionFailedEvent { @@ -1080,7 +1203,12 @@ module aptos_framework::multisig_account { num_approvals_and_rejections_internal(&multisig_account_resource.owners, &transaction) } - fun add_transaction(creator: address, multisig_account: &mut MultisigAccount, transaction: MultisigTransaction) { + fun add_transaction( + creator: address, + multisig_account_address: address, + multisig_account: &mut MultisigAccount, + transaction: MultisigTransaction + ) { if(features::multisig_v2_enhancement_feature_enabled()) { let num_pending_transactions = multisig_account.next_sequence_number - (multisig_account.last_executed_sequence_number + 1); assert!( @@ -1095,6 +1223,11 @@ module aptos_framework::multisig_account { let sequence_number = multisig_account.next_sequence_number; multisig_account.next_sequence_number = sequence_number + 1; table::add(&mut multisig_account.transactions, sequence_number, transaction); + if (std::features::module_event_migration_enabled()) { + emit( + CreateTransaction { multisig_account: multisig_account_address, creator, sequence_number, transaction } + ); + }; emit_event( &mut multisig_account.create_transaction_events, CreateTransactionEvent { creator, sequence_number, transaction }, @@ -1224,6 +1357,9 @@ module aptos_framework::multisig_account { &multisig_account_ref_mut.owners, multisig_address ); + if (std::features::module_event_migration_enabled()) { + emit(AddOwners { multisig_account: multisig_address, owners_added: new_owners }); + }; emit_event( &mut multisig_account_ref_mut.add_owners_events, AddOwnersEvent { owners_added: new_owners } @@ -1245,6 +1381,11 @@ module aptos_framework::multisig_account { }); // Only emit event if owner(s) actually removed. if (vector::length(&owners_removed) > 0) { + if (std::features::module_event_migration_enabled()) { + emit( + RemoveOwners { multisig_account: multisig_address, owners_removed } + ); + }; emit_event( &mut multisig_account_ref_mut.remove_owners_events, RemoveOwnersEvent { owners_removed } @@ -1265,6 +1406,15 @@ module aptos_framework::multisig_account { if (new_num_signatures_required != old_num_signatures_required) { multisig_account_ref_mut.num_signatures_required = new_num_signatures_required; + if (std::features::module_event_migration_enabled()) { + emit( + UpdateSignaturesRequired { + multisig_account: multisig_address, + old_num_signatures_required, + new_num_signatures_required, + } + ); + }; emit_event( &mut multisig_account_ref_mut.update_signature_required_events, UpdateSignaturesRequiredEvent { @@ -1363,7 +1513,7 @@ module aptos_framework::multisig_account { // First transaction has 2 approvals so it can be executed. assert!(can_be_executed(multisig_account, 1), 1); // First transaction was executed successfully. - successful_transaction_execution_cleanup(owner_2_addr, multisig_account,vector[]); + successful_transaction_execution_cleanup(owner_2_addr, multisig_account, vector[]); assert!(get_pending_transactions(multisig_account) == vector[ get_transaction(multisig_account, 2), get_transaction(multisig_account, 3), @@ -1599,7 +1749,7 @@ module aptos_framework::multisig_account { setup(); let owner_addr = address_of(owner); create_account(owner_addr); - create(owner,1, vector[], vector[]); + create(owner, 1, vector[], vector[]); let multisig_account = get_next_multisig_account_address(owner_addr); update_metadata( &create_signer(multisig_account), @@ -1615,10 +1765,10 @@ module aptos_framework::multisig_account { #[test(owner = @0x123)] #[expected_failure(abort_code = 0x1000B, location = Self)] public entry fun test_update_with_zero_signatures_required_should_fail( - owner:& signer) acquires MultisigAccount { + owner: & signer) acquires MultisigAccount { setup(); create_account(address_of(owner)); - create(owner,1, vector[], vector[]); + create(owner, 1, vector[], vector[]); let multisig_account = get_next_multisig_account_address(address_of(owner)); update_signatures_required(&create_signer(multisig_account), 0); } @@ -1629,7 +1779,7 @@ module aptos_framework::multisig_account { owner: &signer) acquires MultisigAccount { setup(); create_account(address_of(owner)); - create(owner,1, vector[], vector[]); + create(owner, 1, vector[], vector[]); let multisig_account = get_next_multisig_account_address(address_of(owner)); update_signatures_required(&create_signer(multisig_account), 2); } @@ -1739,7 +1889,7 @@ module aptos_framework::multisig_account { owner: &signer) acquires MultisigAccount { setup(); create_account(address_of(owner)); - create(owner,1, vector[], vector[]); + create(owner, 1, vector[], vector[]); let multisig_account = get_next_multisig_account_address(address_of(owner)); create_transaction(owner, multisig_account, vector[]); } @@ -1750,7 +1900,7 @@ module aptos_framework::multisig_account { owner: &signer, non_owner: &signer) acquires MultisigAccount { setup(); create_account(address_of(owner)); - create(owner,1, vector[], vector[]); + create(owner, 1, vector[], vector[]); let multisig_account = get_next_multisig_account_address(address_of(owner)); create_transaction(non_owner, multisig_account, PAYLOAD); } @@ -1760,7 +1910,7 @@ module aptos_framework::multisig_account { owner: &signer) acquires MultisigAccount { setup(); create_account(address_of(owner)); - create(owner,1, vector[], vector[]); + create(owner, 1, vector[], vector[]); let multisig_account = get_next_multisig_account_address(address_of(owner)); create_transaction_with_hash(owner, multisig_account, sha3_256(PAYLOAD)); } @@ -1771,7 +1921,7 @@ module aptos_framework::multisig_account { owner: &signer) acquires MultisigAccount { setup(); create_account(address_of(owner)); - create(owner,1, vector[], vector[]); + create(owner, 1, vector[], vector[]); let multisig_account = get_next_multisig_account_address(address_of(owner)); create_transaction_with_hash(owner, multisig_account, vector[]); } @@ -1782,7 +1932,7 @@ module aptos_framework::multisig_account { owner: &signer, non_owner: &signer) acquires MultisigAccount { setup(); create_account(address_of(owner)); - create(owner,1, vector[], vector[]); + create(owner, 1, vector[], vector[]); let multisig_account = get_next_multisig_account_address(address_of(owner)); create_transaction_with_hash(non_owner, multisig_account, sha3_256(PAYLOAD)); } @@ -1810,7 +1960,7 @@ module aptos_framework::multisig_account { #[test(owner_1 = @0x123, owner_2 = @0x124, owner_3 = @0x125)] public entry fun test_validate_transaction_should_not_consider_removed_owners( - owner_1: &signer, owner_2: &signer, owner_3:& signer) acquires MultisigAccount { + owner_1: &signer, owner_2: &signer, owner_3: & signer) acquires MultisigAccount { setup(); let owner_1_addr = address_of(owner_1); let owner_2_addr = address_of(owner_2); @@ -1950,7 +2100,7 @@ module aptos_framework::multisig_account { approve_transaction(owner_2, multisig_account, 1); assert!(can_be_executed(multisig_account, 1), 1); assert!(table::contains(&borrow_global(multisig_account).transactions, 1), 0); - successful_transaction_execution_cleanup(owner_3_addr, multisig_account,vector[]); + successful_transaction_execution_cleanup(owner_3_addr, multisig_account, vector[]); } #[test(owner_1 = @0x123, owner_2 = @0x124, owner_3 = @0x125)] @@ -1969,7 +2119,7 @@ module aptos_framework::multisig_account { approve_transaction(owner_2, multisig_account, 1); assert!(can_be_executed(multisig_account, 1), 1); assert!(table::contains(&borrow_global(multisig_account).transactions, 1), 0); - failed_transaction_execution_cleanup(owner_3_addr, multisig_account,vector[], execution_error()); + failed_transaction_execution_cleanup(owner_3_addr, multisig_account, vector[], execution_error()); } #[test(owner_1 = @0x123, owner_2 = @0x124, owner_3 = @0x125)] @@ -2017,7 +2167,7 @@ module aptos_framework::multisig_account { setup(); create_account(address_of(owner)); let multisig_account = get_next_multisig_account_address(address_of(owner)); - create(owner,1, vector[], vector[]); + create(owner, 1, vector[], vector[]); create_transaction(owner, multisig_account, PAYLOAD); reject_transaction(owner, multisig_account, 1); diff --git a/aptos-move/framework/aptos-framework/sources/object.move b/aptos-move/framework/aptos-framework/sources/object.move index 0543a0b4f7b78..e81b88e5eb9a8 100644 --- a/aptos-move/framework/aptos-framework/sources/object.move +++ b/aptos-move/framework/aptos-framework/sources/object.move @@ -156,7 +156,6 @@ module aptos_framework::object { self: address, } - #[event] /// Emitted whenever the object's owner field is changed. struct TransferEvent has drop, store { object: address, @@ -164,6 +163,14 @@ module aptos_framework::object { to: address, } + #[event] + /// Emitted whenever the object's owner field is changed. + struct Transfer has drop, store { + object: address, + from: address, + to: address, + } + #[view] public fun is_burnt(object: Object): bool { exists(object.inner) @@ -432,13 +439,15 @@ module aptos_framework::object { object.owner == ref.owner, error::permission_denied(ENOT_OBJECT_OWNER), ); - event::emit( - TransferEvent { - object: ref.self, - from: object.owner, - to, - }, - ); + if (std::features::module_event_migration_enabled()) { + event::emit( + Transfer { + object: ref.self, + from: object.owner, + to, + }, + ); + }; event::emit_event( &mut object.transfer_events, TransferEvent { @@ -487,7 +496,7 @@ module aptos_framework::object { let object_core = borrow_global_mut(object); if (object_core.owner != to) { event::emit( - TransferEvent { + Transfer { object, from: object_core.owner, to, diff --git a/aptos-move/framework/aptos-framework/sources/reconfiguration.move b/aptos-move/framework/aptos-framework/sources/reconfiguration.move index 86f96c05ca097..528da4a6d6659 100644 --- a/aptos-move/framework/aptos-framework/sources/reconfiguration.move +++ b/aptos-move/framework/aptos-framework/sources/reconfiguration.move @@ -24,6 +24,7 @@ module aptos_framework::reconfiguration { friend aptos_framework::version; friend aptos_framework::reconfiguration_with_dkg; + #[event] /// Event that signals consensus to start a new epoch, /// with new configuration information. This is also called a /// "reconfiguration event" @@ -31,6 +32,14 @@ module aptos_framework::reconfiguration { epoch: u64, } + #[event] + /// Event that signals consensus to start a new epoch, + /// with new configuration information. This is also called a + /// "reconfiguration event" + struct NewEpoch has drop, store { + epoch: u64, + } + /// Holds information about state of reconfiguration struct Configuration has key { /// Epoch number @@ -154,6 +163,14 @@ module aptos_framework::reconfiguration { }, ); + if (std::features::module_event_migration_enabled()) { + event::emit( + NewEpoch { + epoch: config_ref.epoch, + }, + ); + }; + reconfiguration_state::on_reconfig_finish(); } @@ -172,6 +189,13 @@ module aptos_framework::reconfiguration { assert!(config_ref.epoch == 0 && config_ref.last_reconfiguration_time == 0, error::invalid_state(ECONFIGURATION)); config_ref.epoch = 1; + if (std::features::module_event_migration_enabled()) { + event::emit( + NewEpoch { + epoch: config_ref.epoch, + }, + ); + }; event::emit_event( &mut config_ref.events, NewEpochEvent { diff --git a/aptos-move/framework/aptos-framework/sources/stake.move b/aptos-move/framework/aptos-framework/sources/stake.move index cbac435b748b1..cf0d4576d3959 100644 --- a/aptos-move/framework/aptos-framework/sources/stake.move +++ b/aptos-move/framework/aptos-framework/sources/stake.move @@ -204,28 +204,59 @@ module aptos_framework::stake { pool_address: address, } + #[event] + struct RegisterValidatorCandidate has drop, store { + pool_address: address, + } + struct SetOperatorEvent has drop, store { pool_address: address, old_operator: address, new_operator: address, } + #[event] + struct SetOperator has drop, store { + pool_address: address, + old_operator: address, + new_operator: address, + } + struct AddStakeEvent has drop, store { pool_address: address, amount_added: u64, } + #[event] + struct AddStake has drop, store { + pool_address: address, + amount_added: u64, + } + struct ReactivateStakeEvent has drop, store { pool_address: address, amount: u64, } + #[event] + struct ReactivateStake has drop, store { + pool_address: address, + amount: u64, + } + struct RotateConsensusKeyEvent has drop, store { pool_address: address, old_consensus_pubkey: vector, new_consensus_pubkey: vector, } + #[event] + struct RotateConsensusKey has drop, store { + pool_address: address, + old_consensus_pubkey: vector, + new_consensus_pubkey: vector, + } + struct UpdateNetworkAndFullnodeAddressesEvent has drop, store { pool_address: address, old_network_addresses: vector, @@ -234,35 +265,79 @@ module aptos_framework::stake { new_fullnode_addresses: vector, } + #[event] + struct UpdateNetworkAndFullnodeAddresses has drop, store { + pool_address: address, + old_network_addresses: vector, + new_network_addresses: vector, + old_fullnode_addresses: vector, + new_fullnode_addresses: vector, + } + struct IncreaseLockupEvent has drop, store { pool_address: address, old_locked_until_secs: u64, new_locked_until_secs: u64, } + #[event] + struct IncreaseLockup has drop, store { + pool_address: address, + old_locked_until_secs: u64, + new_locked_until_secs: u64, + } + struct JoinValidatorSetEvent has drop, store { pool_address: address, } + #[event] + struct JoinValidatorSet has drop, store { + pool_address: address, + } + struct DistributeRewardsEvent has drop, store { pool_address: address, rewards_amount: u64, } + #[event] + struct DistributeRewards has drop, store { + pool_address: address, + rewards_amount: u64, + } + struct UnlockStakeEvent has drop, store { pool_address: address, amount_unlocked: u64, } + #[event] + struct UnlockStake has drop, store { + pool_address: address, + amount_unlocked: u64, + } + struct WithdrawStakeEvent has drop, store { pool_address: address, amount_withdrawn: u64, } + #[event] + struct WithdrawStake has drop, store { + pool_address: address, + amount_withdrawn: u64, + } + struct LeaveValidatorSetEvent has drop, store { pool_address: address, } + #[event] + struct LeaveValidatorSet has drop, store { + pool_address: address, + } + /// Stores transaction fees assigned to validators. All fees are distributed to validators /// at the end of the epoch. struct ValidatorFees has key { @@ -393,7 +468,9 @@ module aptos_framework::stake { #[view] /// Return the validator's config. - public fun get_validator_config(pool_address: address): (vector, vector, vector) acquires ValidatorConfig { + public fun get_validator_config( + pool_address: address + ): (vector, vector, vector) acquires ValidatorConfig { assert_stake_pool_exists(pool_address); let validator_config = borrow_global(pool_address); (validator_config.consensus_pubkey, validator_config.network_addresses, validator_config.fullnode_addresses) @@ -545,7 +622,9 @@ module aptos_framework::stake { add_stake_events: account::new_event_handle(owner), reactivate_stake_events: account::new_event_handle(owner), rotate_consensus_key_events: account::new_event_handle(owner), - update_network_and_fullnode_addresses_events: account::new_event_handle(owner), + update_network_and_fullnode_addresses_events: account::new_event_handle( + owner + ), increase_lockup_events: account::new_event_handle(owner), join_validator_set_events: account::new_event_handle(owner), distribute_rewards_events: account::new_event_handle(owner), @@ -592,6 +671,16 @@ module aptos_framework::stake { let old_operator = stake_pool.operator_address; stake_pool.operator_address = new_operator; + if (std::features::module_event_migration_enabled()) { + event::emit( + SetOperator { + pool_address, + old_operator, + new_operator, + }, + ); + }; + event::emit_event( &mut stake_pool.set_operator_events, SetOperatorEvent { @@ -661,6 +750,14 @@ module aptos_framework::stake { let voting_power = get_next_epoch_voting_power(stake_pool); assert!(voting_power <= maximum_stake, error::invalid_argument(ESTAKE_EXCEEDS_MAX)); + if (std::features::module_event_migration_enabled()) { + event::emit( + AddStake { + pool_address, + amount_added: amount, + }, + ); + }; event::emit_event( &mut stake_pool.add_stake_events, AddStakeEvent { @@ -695,6 +792,14 @@ module aptos_framework::stake { let reactivated_coins = coin::extract(&mut stake_pool.pending_inactive, amount); coin::merge(&mut stake_pool.active, reactivated_coins); + if (std::features::module_event_migration_enabled()) { + event::emit( + ReactivateStake { + pool_address, + amount, + }, + ); + }; event::emit_event( &mut stake_pool.reactivate_stake_events, ReactivateStakeEvent { @@ -728,6 +833,15 @@ module aptos_framework::stake { assert!(option::is_some(pubkey_from_pop), error::invalid_argument(EINVALID_PUBLIC_KEY)); validator_info.consensus_pubkey = new_consensus_pubkey; + if (std::features::module_event_migration_enabled()) { + event::emit( + RotateConsensusKey { + pool_address, + old_consensus_pubkey, + new_consensus_pubkey, + }, + ); + }; event::emit_event( &mut stake_pool.rotate_consensus_key_events, RotateConsensusKeyEvent { @@ -756,6 +870,17 @@ module aptos_framework::stake { let old_fullnode_addresses = validator_info.fullnode_addresses; validator_info.fullnode_addresses = new_fullnode_addresses; + if (std::features::module_event_migration_enabled()) { + event::emit( + UpdateNetworkAndFullnodeAddresses { + pool_address, + old_network_addresses, + new_network_addresses, + old_fullnode_addresses, + new_fullnode_addresses, + }, + ); + }; event::emit_event( &mut stake_pool.update_network_and_fullnode_addresses_events, UpdateNetworkAndFullnodeAddressesEvent { @@ -766,6 +891,7 @@ module aptos_framework::stake { new_fullnode_addresses, }, ); + } /// Similar to increase_lockup_with_cap but will use ownership capability from the signing account. @@ -789,6 +915,15 @@ module aptos_framework::stake { assert!(old_locked_until_secs < new_locked_until_secs, error::invalid_argument(EINVALID_LOCKUP)); stake_pool.locked_until_secs = new_locked_until_secs; + if (std::features::module_event_migration_enabled()) { + event::emit( + IncreaseLockup { + pool_address, + old_locked_until_secs, + new_locked_until_secs, + }, + ); + }; event::emit_event( &mut stake_pool.increase_lockup_events, IncreaseLockupEvent { @@ -846,10 +981,18 @@ module aptos_framework::stake { // Validate the current validator set size has not exceeded the limit. let validator_set = borrow_global_mut(@aptos_framework); - vector::push_back(&mut validator_set.pending_active, generate_validator_info(pool_address, stake_pool, *validator_config)); - let validator_set_size = vector::length(&validator_set.active_validators) + vector::length(&validator_set.pending_active); + vector::push_back( + &mut validator_set.pending_active, + generate_validator_info(pool_address, stake_pool, *validator_config) + ); + let validator_set_size = vector::length(&validator_set.active_validators) + vector::length( + &validator_set.pending_active + ); assert!(validator_set_size <= MAX_VALIDATOR_SET_SIZE, error::invalid_argument(EVALIDATOR_SET_TOO_LARGE)); + if (std::features::module_event_migration_enabled()) { + event::emit(JoinValidatorSet { pool_address }); + }; event::emit_event( &mut stake_pool.join_validator_set_events, JoinValidatorSetEvent { pool_address }, @@ -883,6 +1026,14 @@ module aptos_framework::stake { let unlocked_stake = coin::extract(&mut stake_pool.active, amount); coin::merge(&mut stake_pool.pending_inactive, unlocked_stake); + if (std::features::module_event_migration_enabled()) { + event::emit( + UnlockStake { + pool_address, + amount_unlocked: amount, + }, + ); + }; event::emit_event( &mut stake_pool.unlock_stake_events, UnlockStakeEvent { @@ -926,6 +1077,14 @@ module aptos_framework::stake { withdraw_amount = min(withdraw_amount, coin::value(&stake_pool.inactive)); if (withdraw_amount == 0) return coin::zero(); + if (std::features::module_event_migration_enabled()) { + event::emit( + WithdrawStake { + pool_address, + amount_withdrawn: withdraw_amount, + }, + ); + }; event::emit_event( &mut stake_pool.withdraw_stake_events, WithdrawStakeEvent { @@ -987,6 +1146,9 @@ module aptos_framework::stake { assert!(vector::length(&validator_set.active_validators) > 0, error::invalid_state(ELAST_VALIDATOR)); vector::push_back(&mut validator_set.pending_inactive, validator_info); + if (std::features::module_event_migration_enabled()) { + event::emit(LeaveValidatorSet { pool_address }); + }; event::emit_event( &mut stake_pool.leave_validator_set_events, LeaveValidatorSetEvent { @@ -1007,7 +1169,10 @@ module aptos_framework::stake { /// Update the validator performance (proposal statistics). This is only called by block::prologue(). /// This function cannot abort. - public(friend) fun update_performance_statistics(proposer_index: Option, failed_proposer_indices: vector) acquires ValidatorPerformance { + public(friend) fun update_performance_statistics( + proposer_index: Option, + failed_proposer_indices: vector + ) acquires ValidatorPerformance { // Validator set cannot change until the end of the epoch, so the validator index in arguments should // match with those of the validators in ValidatorPerformance resource. let validator_perf = borrow_global_mut(@aptos_framework); @@ -1036,7 +1201,9 @@ module aptos_framework::stake { while ({ spec { invariant len(validator_perf.validators) == validator_len; - invariant (option::spec_is_some(ghost_proposer_idx) && option::spec_borrow(ghost_proposer_idx) < validator_len) ==> + invariant (option::spec_is_some(ghost_proposer_idx) && option::spec_borrow( + ghost_proposer_idx + ) < validator_len) ==> (validator_perf.validators[option::spec_borrow(ghost_proposer_idx)].successful_proposals == ghost_valid_perf.validators[option::spec_borrow(ghost_proposer_idx)].successful_proposals + 1); }; @@ -1064,7 +1231,8 @@ module aptos_framework::stake { /// pending inactive validators so they no longer can vote. /// 4. The validator's voting power in the validator set is updated to be the corresponding staking pool's voting /// power. - public(friend) fun on_new_epoch() acquires StakePool, AptosCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { + public(friend) fun on_new_epoch( + ) acquires StakePool, AptosCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { let validator_set = borrow_global_mut(@aptos_framework); let config = staking_config::get(); let validator_perf = borrow_global_mut(@aptos_framework); @@ -1429,6 +1597,9 @@ module aptos_framework::stake { ); }; + if (std::features::module_event_migration_enabled()) { + event::emit(DistributeRewards { pool_address, rewards_amount }); + }; event::emit_event( &mut stake_pool.distribute_rewards_events, DistributeRewardsEvent { @@ -1483,7 +1654,13 @@ module aptos_framework::stake { ): u64 acquires AptosCoinCapabilities { let stake_amount = coin::value(stake); let rewards_amount = if (stake_amount > 0) { - calculate_rewards_amount(stake_amount, num_successful_proposals, num_total_proposals, rewards_rate, rewards_rate_denominator) + calculate_rewards_amount( + stake_amount, + num_successful_proposals, + num_total_proposals, + rewards_rate, + rewards_rate_denominator + ) } else { 0 }; @@ -1564,7 +1741,10 @@ module aptos_framework::stake { accounts: vector
, } - public fun configure_allowed_validators(aptos_framework: &signer, accounts: vector
) acquires AllowedValidators { + public fun configure_allowed_validators( + aptos_framework: &signer, + accounts: vector
+ ) acquires AllowedValidators { let aptos_framework_address = signer::address_of(aptos_framework); system_addresses::assert_aptos_framework(aptos_framework); if (!exists(aptos_framework_address)) { @@ -2413,11 +2593,29 @@ module aptos_framework::stake { join_validator_set(validator_3, validator_3_address); // Validator 2 is not effectively removed until next epoch. assert!(get_validator_state(validator_2_address) == VALIDATOR_STATUS_PENDING_INACTIVE, 6); - assert!(vector::borrow(&borrow_global(@aptos_framework).pending_inactive, 0).addr == validator_2_address, 0); + assert!( + vector::borrow( + &borrow_global(@aptos_framework).pending_inactive, + 0 + ).addr == validator_2_address, + 0 + ); // Validator 3 is not effectively added until next epoch. assert!(get_validator_state(validator_3_address) == VALIDATOR_STATUS_PENDING_ACTIVE, 7); - assert!(vector::borrow(&borrow_global(@aptos_framework).pending_active, 0).addr == validator_3_address, 0); - assert!(vector::borrow(&borrow_global(@aptos_framework).active_validators, 0).config.consensus_pubkey == pk_1_bytes, 0); + assert!( + vector::borrow( + &borrow_global(@aptos_framework).pending_active, + 0 + ).addr == validator_3_address, + 0 + ); + assert!( + vector::borrow( + &borrow_global(@aptos_framework).active_validators, + 0 + ).config.consensus_pubkey == pk_1_bytes, + 0 + ); // Changes applied after new epoch end_epoch(); @@ -2429,7 +2627,13 @@ module aptos_framework::stake { assert_validator_state(validator_2_address, 101, 0, 0, 0, 1); assert!(get_validator_state(validator_3_address) == VALIDATOR_STATUS_ACTIVE, 10); assert_validator_state(validator_3_address, 100, 0, 0, 0, 1); - assert!(vector::borrow(&borrow_global(@aptos_framework).active_validators, 0).config.consensus_pubkey == pk_1b_bytes, 0); + assert!( + vector::borrow( + &borrow_global(@aptos_framework).active_validators, + 0 + ).config.consensus_pubkey == pk_1b_bytes, + 0 + ); // Validators without enough stake will be removed. unlock(validator_1, 50); @@ -2928,7 +3132,8 @@ module aptos_framework::stake { } #[test_only] - public fun end_epoch() acquires StakePool, AptosCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { + public fun end_epoch( + ) acquires StakePool, AptosCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { // Set the number of blocks to 1, to give out rewards to non-failing validators. set_validator_perf_at_least_one_block(); timestamp::fast_forward_seconds(EPOCH_DURATION); diff --git a/aptos-move/framework/aptos-framework/sources/staking_contract.move b/aptos-move/framework/aptos-framework/sources/staking_contract.move index ed05e51325dd1..8de013987e7b9 100644 --- a/aptos-move/framework/aptos-framework/sources/staking_contract.move +++ b/aptos-move/framework/aptos-framework/sources/staking_contract.move @@ -66,7 +66,7 @@ module aptos_framework::staking_contract { /// Maximum number of distributions a stake pool can support. const MAXIMUM_PENDING_DISTRIBUTIONS: u64 = 20; - #[resource_group(scope=module_)] + #[resource_group(scope = module_)] struct StakingGroupContainer {} struct StakingContract has store { @@ -109,11 +109,94 @@ module aptos_framework::staking_contract { new_commission_percentage: u64, } + #[event] + struct UpdateCommission has drop, store { + staker: address, + operator: address, + old_commission_percentage: u64, + new_commission_percentage: u64, + } + #[resource_group_member(group = aptos_framework::staking_contract::StakingGroupContainer)] struct StakingGroupUpdateCommissionEvent has key { update_commission_events: EventHandle, } + #[event] + struct CreateStakingContract has drop, store { + operator: address, + voter: address, + pool_address: address, + principal: u64, + commission_percentage: u64, + } + + #[event] + struct UpdateVoter has drop, store { + operator: address, + pool_address: address, + old_voter: address, + new_voter: address, + } + + #[event] + struct ResetLockup has drop, store { + operator: address, + pool_address: address, + } + + #[event] + struct AddStake has drop, store { + operator: address, + pool_address: address, + amount: u64 + } + + #[event] + struct RequestCommission has drop, store { + operator: address, + pool_address: address, + accumulated_rewards: u64, + commission_amount: u64, + } + + #[event] + struct UnlockStake has drop, store { + operator: address, + pool_address: address, + amount: u64, + commission_paid: u64, + } + + #[event] + struct SwitchOperator has drop, store { + old_operator: address, + new_operator: address, + pool_address: address, + } + + #[event] + struct AddDistribution has drop, store { + operator: address, + pool_address: address, + amount: u64, + } + + #[event] + struct Distribute has drop, store { + operator: address, + pool_address: address, + recipient: address, + amount: u64, + } + + #[event] + struct SetBeneficiaryForOperator has drop, store { + operator: address, + old_beneficiary: address, + new_beneficiary: address, + } + struct CreateStakingContractEvent has drop, store { operator: address, voter: address, @@ -173,13 +256,6 @@ module aptos_framework::staking_contract { amount: u64, } - #[event] - struct SetBeneficiaryForOperator has drop, store { - operator: address, - old_beneficiary: address, - new_beneficiary: address, - } - #[view] /// Return the address of the underlying stake pool for the staking contract between the provided staker and /// operator. @@ -340,6 +416,9 @@ module aptos_framework::staking_contract { signer_cap: stake_pool_signer_cap, }); + if (std::features::module_event_migration_enabled()) { + emit(CreateStakingContract { operator, voter, pool_address, principal, commission_percentage }); + }; emit_event( &mut store.create_staking_contract_events, CreateStakingContractEvent { operator, voter, pool_address, principal, commission_percentage }, @@ -361,6 +440,9 @@ module aptos_framework::staking_contract { staking_contract.principal = staking_contract.principal + amount; let pool_address = staking_contract.pool_address; + if (std::features::module_event_migration_enabled()) { + emit(AddStake { operator, pool_address, amount }); + }; emit_event( &mut store.add_stake_events, AddStakeEvent { operator, pool_address, amount }, @@ -378,10 +460,14 @@ module aptos_framework::staking_contract { let old_voter = stake::get_delegated_voter(pool_address); stake::set_delegated_voter_with_cap(&staking_contract.owner_cap, new_voter); + if (std::features::module_event_migration_enabled()) { + emit(UpdateVoter { operator, pool_address, old_voter, new_voter }); + }; emit_event( &mut store.update_voter_events, UpdateVoterEvent { operator, pool_address, old_voter, new_voter }, ); + } /// Convenient function to allow the staker to reset their stake pool's lockup period to start now. @@ -394,12 +480,19 @@ module aptos_framework::staking_contract { let pool_address = staking_contract.pool_address; stake::increase_lockup_with_cap(&staking_contract.owner_cap); + if (std::features::module_event_migration_enabled()) { + emit(ResetLockup { operator, pool_address }); + }; emit_event(&mut store.reset_lockup_events, ResetLockupEvent { operator, pool_address }); } /// Convenience function to allow a staker to update the commission percentage paid to the operator. /// TODO: fix the typo in function name. commision -> commission - public entry fun update_commision(staker: &signer, operator: address, new_commission_percentage: u64) acquires Store, StakingGroupUpdateCommissionEvent, BeneficiaryForOperator { + public entry fun update_commision( + staker: &signer, + operator: address, + new_commission_percentage: u64 + ) acquires Store, BeneficiaryForOperator, StakingGroupUpdateCommissionEvent { assert!( new_commission_percentage >= 0 && new_commission_percentage <= 100, error::invalid_argument(EINVALID_COMMISSION_PERCENTAGE), @@ -420,7 +513,19 @@ module aptos_framework::staking_contract { let old_commission_percentage = staking_contract.commission_percentage; staking_contract.commission_percentage = new_commission_percentage; if (!exists(staker_address)) { - move_to(staker, StakingGroupUpdateCommissionEvent { update_commission_events: account::new_event_handle(staker)}) + move_to( + staker, + StakingGroupUpdateCommissionEvent { + update_commission_events: account::new_event_handle( + staker + ) + } + ) + }; + if (std::features::module_event_migration_enabled()) { + emit( + UpdateCommission { staker: staker_address, operator, old_commission_percentage, new_commission_percentage } + ); }; emit_event( &mut borrow_global_mut(staker_address).update_commission_events, @@ -432,7 +537,11 @@ module aptos_framework::staking_contract { /// at the end of the stake pool's lockup period before they can actually can withdraw_commission. /// /// Only staker, operator or beneficiary can call this. - public entry fun request_commission(account: &signer, staker: address, operator: address) acquires Store, BeneficiaryForOperator { + public entry fun request_commission( + account: &signer, + staker: address, + operator: address + ) acquires Store, BeneficiaryForOperator { let account_addr = signer::address_of(account); assert!( account_addr == staker || account_addr == operator || account_addr == beneficiary_for_operator(operator), @@ -482,6 +591,9 @@ module aptos_framework::staking_contract { stake::unlock_with_cap(commission_amount, &staking_contract.owner_cap); let pool_address = staking_contract.pool_address; + if (std::features::module_event_migration_enabled()) { + emit(RequestCommission { operator, pool_address, accumulated_rewards, commission_amount }); + }; emit_event( request_commission_events, RequestCommissionEvent { operator, pool_address, accumulated_rewards, commission_amount }, @@ -492,7 +604,11 @@ module aptos_framework::staking_contract { /// Staker can call this to request withdrawal of part or all of their staking_contract. /// This also triggers paying commission to the operator for accounting simplicity. - public entry fun unlock_stake(staker: &signer, operator: address, amount: u64) acquires Store, BeneficiaryForOperator { + public entry fun unlock_stake( + staker: &signer, + operator: address, + amount: u64 + ) acquires Store, BeneficiaryForOperator { // Short-circuit if amount is 0. if (amount == 0) return; @@ -523,14 +639,16 @@ module aptos_framework::staking_contract { staking_contract.principal = staking_contract.principal - amount; // Record a distribution for the staker. - add_distribution( - operator, staking_contract, staker_address, amount, &mut store.add_distribution_events); + add_distribution(operator, staking_contract, staker_address, amount, &mut store.add_distribution_events); // Request to unlock the distribution amount from the stake pool. // This won't become fully unlocked until the stake pool's lockup expires. stake::unlock_with_cap(amount, &staking_contract.owner_cap); let pool_address = staking_contract.pool_address; + if (std::features::module_event_migration_enabled()) { + emit(UnlockStake { pool_address, operator, amount, commission_paid }); + }; emit_event( &mut store.unlock_stake_events, UnlockStakeEvent { pool_address, operator, amount, commission_paid }, @@ -598,6 +716,9 @@ module aptos_framework::staking_contract { let pool_address = staking_contract.pool_address; simple_map::add(staking_contracts, new_operator, staking_contract); + if (std::features::module_event_migration_enabled()) { + emit(SwitchOperator { pool_address, old_operator, new_operator }); + }; emit_event( &mut store.switch_operator_events, SwitchOperatorEvent { pool_address, old_operator, new_operator } @@ -607,7 +728,10 @@ module aptos_framework::staking_contract { /// Allows an operator to change its beneficiary. Any existing unpaid commission rewards will be paid to the new /// beneficiary. To ensures payment to the current beneficiary, one should first call `distribute` before switching /// the beneficiary. An operator can set one beneficiary for staking contract pools, not a separate one for each pool. - public entry fun set_beneficiary_for_operator(operator: &signer, new_beneficiary: address) acquires BeneficiaryForOperator { + public entry fun set_beneficiary_for_operator( + operator: &signer, + new_beneficiary: address + ) acquires BeneficiaryForOperator { assert!(features::operator_beneficiary_change_enabled(), std::error::invalid_state( EOPERATOR_BENEFICIARY_CHANGE_NOT_SUPPORTED )); @@ -670,6 +794,9 @@ module aptos_framework::staking_contract { }; aptos_account::deposit_coins(recipient, coin::extract(&mut coins, amount_to_distribute)); + if (std::features::module_event_migration_enabled()) { + emit(Distribute { operator, pool_address, recipient, amount: amount_to_distribute }); + }; emit_event( distribute_events, DistributeEvent { operator, pool_address, recipient, amount: amount_to_distribute } @@ -701,7 +828,7 @@ module aptos_framework::staking_contract { staking_contract: &mut StakingContract, recipient: address, coins_amount: u64, - add_distribution_events: &mut EventHandle, + add_distribution_events: &mut EventHandle ) { let distribution_pool = &mut staking_contract.distribution_pool; let (_, _, _, total_distribution_amount) = stake::get_stake(staking_contract.pool_address); @@ -710,6 +837,9 @@ module aptos_framework::staking_contract { pool_u64::buy_in(distribution_pool, recipient, coins_amount); let pool_address = staking_contract.pool_address; + if (std::features::module_event_migration_enabled()) { + emit(AddDistribution { operator, pool_address, amount: coins_amount }); + }; emit_event( add_distribution_events, AddDistributionEvent { operator, pool_address, amount: coins_amount } @@ -840,7 +970,16 @@ module aptos_framework::staking_contract { #[test_only] public fun setup(aptos_framework: &signer, staker: &signer, operator: &signer, initial_balance: u64) { // Reward rate of 0.1% per epoch. - stake::initialize_for_test_custom(aptos_framework, INITIAL_BALANCE, MAXIMUM_STAKE, 3600, true, 10, 10000, 1000000); + stake::initialize_for_test_custom( + aptos_framework, + INITIAL_BALANCE, + MAXIMUM_STAKE, + 3600, + true, + 10, + 10000, + 1000000 + ); let staker_address = signer::address_of(staker); if (!account::exists_at(staker_address)) { @@ -871,7 +1010,11 @@ module aptos_framework::staking_contract { } #[test(aptos_framework = @0x1, staker = @0x123, operator = @0x234)] - public entry fun test_end_to_end(aptos_framework: &signer, staker: &signer, operator: &signer) acquires Store, BeneficiaryForOperator { + public entry fun test_end_to_end( + aptos_framework: &signer, + staker: &signer, + operator: &signer + ) acquires Store, BeneficiaryForOperator { setup_staking_contract(aptos_framework, staker, operator, INITIAL_BALANCE, 10); let staker_address = signer::address_of(staker); let operator_address = signer::address_of(operator); @@ -1405,8 +1548,13 @@ module aptos_framework::staking_contract { assert_distribution(staker_address, operator_address, staker_address, withdrawn_stake); assert!(last_recorded_principal(staker_address, operator_address) == new_balance, 0); } + #[test(aptos_framework = @0x1, staker = @0x123, operator = @0x234)] - public entry fun test_update_commission(aptos_framework: &signer, staker: &signer, operator: &signer) acquires Store, StakingGroupUpdateCommissionEvent, BeneficiaryForOperator { + public entry fun test_update_commission( + aptos_framework: &signer, + staker: &signer, + operator: &signer + ) acquires Store, BeneficiaryForOperator, StakingGroupUpdateCommissionEvent { let initial_balance = INITIAL_BALANCE * 2; setup_staking_contract(aptos_framework, staker, operator, initial_balance, 10); let staker_address = signer::address_of(staker); @@ -1430,7 +1578,10 @@ module aptos_framework::staking_contract { stake::assert_stake_pool(pool_address, balance_2epoch, 0, 0, with_rewards(unpaid_commission)); } - #[test(staker = @0xe256f4f4e2986cada739e339895cf5585082ff247464cab8ec56eea726bd2263, operator= @0x9f0a211d218b082987408f1e393afe1ba0c202c6d280f081399788d3360c7f09)] + #[test( + staker = @0xe256f4f4e2986cada739e339895cf5585082ff247464cab8ec56eea726bd2263, + operator = @0x9f0a211d218b082987408f1e393afe1ba0c202c6d280f081399788d3360c7f09 + )] public entry fun test_get_expected_stake_pool_address(staker: address, operator: address) { let pool_address = get_expected_stake_pool_address(staker, operator, vector[0x42, 0x42]); assert!(pool_address == @0x9d9648031ada367c26f7878eb0b0406ae6a969b1a43090269e5cdfabe1b48f0f, 0); @@ -1441,7 +1592,10 @@ module aptos_framework::staking_contract { staker: address, operator: address, principal: u64, commission_percentage: u64) acquires Store { let staking_contract = simple_map::borrow(&borrow_global(staker).staking_contracts, &operator); assert!(staking_contract.principal == principal, staking_contract.principal); - assert!(staking_contract.commission_percentage == commission_percentage, staking_contract.commission_percentage); + assert!( + staking_contract.commission_percentage == commission_percentage, + staking_contract.commission_percentage + ); } #[test_only] diff --git a/aptos-move/framework/aptos-framework/sources/staking_contract.spec.move b/aptos-move/framework/aptos-framework/sources/staking_contract.spec.move index 569205a76d91b..31ee882715c71 100644 --- a/aptos-move/framework/aptos-framework/sources/staking_contract.spec.move +++ b/aptos-move/framework/aptos-framework/sources/staking_contract.spec.move @@ -76,7 +76,6 @@ spec aptos_framework::staking_contract { include ContractExistsAbortsIf; let staking_contracts = global(staker).staking_contracts; ensures result == simple_map::spec_get(staking_contracts, operator).pool_address; - } /// Staking_contract exists the stacker/operator pair. @@ -102,7 +101,7 @@ spec aptos_framework::staking_contract { let staking_contract = simple_map::spec_get(staking_contracts, operator); include ContractExistsAbortsIf; - include GetStakingContractAmountsAbortsIf{staking_contract}; + include GetStakingContractAmountsAbortsIf { staking_contract }; let pool_address = staking_contract.pool_address; let stake_pool = global(pool_address); @@ -143,17 +142,17 @@ spec aptos_framework::staking_contract { /// Account is not frozen and sufficient to withdraw. spec create_staking_contract( - staker: &signer, - operator: address, - voter: address, - amount: u64, - commission_percentage: u64, - contract_creation_seed: vector, + staker: &signer, + operator: address, + voter: address, + amount: u64, + commission_percentage: u64, + contract_creation_seed: vector, ) { pragma aborts_if_is_partial; pragma verify_duration_estimate = 120; include PreconditionsInCreateContract; - include WithdrawAbortsIf {account: staker}; + include WithdrawAbortsIf { account: staker }; include CreateStakingContractWithCoinsAbortsIfAndEnsures; } @@ -161,12 +160,12 @@ spec aptos_framework::staking_contract { /// Initialize Store resource if this is the first time the staker has delegated to anyone. /// Cannot create the staking contract if it already exists. spec create_staking_contract_with_coins( - staker: &signer, - operator: address, - voter: address, - coins: Coin, - commission_percentage: u64, - contract_creation_seed: vector, + staker: &signer, + operator: address, + voter: address, + coins: Coin, + commission_percentage: u64, + contract_creation_seed: vector, ): address { pragma verify_duration_estimate = 120; pragma aborts_if_is_partial; @@ -197,7 +196,7 @@ spec aptos_framework::staking_contract { let store = global(staker_address); let staking_contract = simple_map::spec_get(store.staking_contracts, operator); - include WithdrawAbortsIf{account: staker}; + include WithdrawAbortsIf { account: staker }; let balance = global>(staker_address).coin.value; let post post_coin = global>(staker_address).coin.value; ensures post_coin == balance - amount; @@ -219,7 +218,7 @@ spec aptos_framework::staking_contract { /// Staking_contract exists the stacker/operator pair. spec update_voter(staker: &signer, operator: address, new_voter: address) { let staker_address = signer::address_of(staker); - include UpdateVoterSchema {staker: staker_address}; + include UpdateVoterSchema { staker: staker_address }; let post store = global(staker_address); let post staking_contract = simple_map::spec_get(store.staking_contracts, operator); @@ -235,8 +234,8 @@ spec aptos_framework::staking_contract { spec reset_lockup(staker: &signer, operator: address) { let staker_address = signer::address_of(staker); /// [high-level-req-5] - include ContractExistsAbortsIf{staker: staker_address}; - include IncreaseLockupWithCapAbortsIf{staker: staker_address}; + include ContractExistsAbortsIf { staker: staker_address }; + include IncreaseLockupWithCapAbortsIf { staker: staker_address }; } spec update_commision (staker: &signer, operator: address, new_commission_percentage: u64) { @@ -245,7 +244,7 @@ spec aptos_framework::staking_contract { pragma verify = false; let staker_address = signer::address_of(staker); aborts_if new_commission_percentage > 100; - include ContractExistsAbortsIf{staker: staker_address}; + include ContractExistsAbortsIf { staker: staker_address }; } /// Only staker or operator can call this. @@ -254,15 +253,15 @@ spec aptos_framework::staking_contract { // TODO: A data invariant not hold happened here involve with 'pool_u64' #L16. pragma verify = false; let account_addr = signer::address_of(account); - include ContractExistsAbortsIf{staker}; + include ContractExistsAbortsIf { staker }; aborts_if account_addr != staker && account_addr != operator; } spec request_commission_internal( - operator: address, - staking_contract: &mut StakingContract, - add_distribution_events: &mut EventHandle, - request_commission_events: &mut EventHandle, + operator: address, + staking_contract: &mut StakingContract, + add_distribution_events: &mut EventHandle, + request_commission_events: &mut EventHandle, ): u64 { // TODO: A data invariant not hold happened here involve with 'pool_u64' #L16. pragma verify = false; @@ -279,7 +278,7 @@ spec aptos_framework::staking_contract { let staker_address = signer::address_of(staker); let staking_contracts = global(staker_address).staking_contracts; let staking_contract = simple_map::spec_get(staking_contracts, operator); - include ContractExistsAbortsIf{staker: staker_address}; + include ContractExistsAbortsIf { staker: staker_address }; } spec unlock_stake(staker: &signer, operator: address, amount: u64) { @@ -288,33 +287,33 @@ spec aptos_framework::staking_contract { pragma verify = false; requires amount > 0; let staker_address = signer::address_of(staker); - include ContractExistsAbortsIf{staker: staker_address}; + include ContractExistsAbortsIf { staker: staker_address }; } /// Staking_contract exists the stacker/operator pair. spec switch_operator_with_same_commission( - staker: &signer, - old_operator: address, - new_operator: address, + staker: &signer, + old_operator: address, + new_operator: address, ) { // TODO: Call `update_distribution_pool` and could not verify `update_distribution_pool`. pragma aborts_if_is_partial; let staker_address = signer::address_of(staker); - include ContractExistsAbortsIf{staker: staker_address, operator: old_operator}; + include ContractExistsAbortsIf { staker: staker_address, operator: old_operator }; } /// Staking_contract exists the stacker/operator pair. spec switch_operator( - staker: &signer, - old_operator: address, - new_operator: address, - new_commission_percentage: u64, + staker: &signer, + old_operator: address, + new_operator: address, + new_commission_percentage: u64, ) { // TODO: Call `update_distribution_pool` and could not verify `update_distribution_pool`. // TODO: Set because of timeout (estimate unknown). pragma verify = false; let staker_address = signer::address_of(staker); - include ContractExistsAbortsIf{staker: staker_address, operator: old_operator}; + include ContractExistsAbortsIf { staker: staker_address, operator: old_operator }; let store = global(staker_address); let staking_contracts = store.staking_contracts; aborts_if simple_map::spec_contains_key(staking_contracts, new_operator); @@ -340,10 +339,10 @@ spec aptos_framework::staking_contract { /// The StakePool exists under the pool_address of StakingContract. /// The value of inactive and pending_inactive in the stake_pool is up to MAX_U64. spec distribute_internal( - staker: address, - operator: address, - staking_contract: &mut StakingContract, - distribute_events: &mut EventHandle, + staker: address, + operator: address, + staking_contract: &mut StakingContract, + distribute_events: &mut EventHandle, ) { // TODO: Call `update_distribution_pool` and could not verify `update_distribution_pool`. pragma aborts_if_is_partial; @@ -360,11 +359,11 @@ spec aptos_framework::staking_contract { } spec add_distribution( - operator: address, - staking_contract: &mut StakingContract, - recipient: address, - coins_amount: u64, - add_distribution_events: &mut EventHandle, + operator: address, + staking_contract: &mut StakingContract, + recipient: address, + coins_amount: u64, + add_distribution_events: &mut EventHandle, ) { // TODO: Call `update_distribution_pool` and could not verify `update_distribution_pool`. pragma verify = false; @@ -387,11 +386,12 @@ spec aptos_framework::staking_contract { } spec create_stake_pool( - staker: &signer, - operator: address, - voter: address, - contract_creation_seed: vector, + staker: &signer, + operator: address, + voter: address, + contract_creation_seed: vector, ): (signer, SignerCapability, OwnerCapability) { + pragma verify_duration_estimate = 120; include stake::ResourceRequirement; let staker_address = signer::address_of(staker); // postconditions account::create_resource_account() @@ -399,7 +399,7 @@ spec aptos_framework::staking_contract { let seed_0 = bcs::to_bytes(staker_address); let seed_1 = concat(concat(concat(seed_0, bcs::to_bytes(operator)), SALT), contract_creation_seed); let resource_addr = account::spec_create_resource_address(staker_address, seed_1); - include CreateStakePoolAbortsIf {resource_addr}; + include CreateStakePoolAbortsIf { resource_addr }; ensures exists(resource_addr); let post post_account = global(resource_addr); ensures post_account.authentication_key == account::ZERO_AUTH_KEY; @@ -420,10 +420,10 @@ spec aptos_framework::staking_contract { } spec update_distribution_pool( - distribution_pool: &mut Pool, - updated_total_coins: u64, - operator: address, - commission_percentage: u64, + distribution_pool: &mut Pool, + updated_total_coins: u64, + operator: address, + commission_percentage: u64, ) { // TODO: complex aborts conditions in the cycle. // pragma verify = false; @@ -498,7 +498,7 @@ spec aptos_framework::staking_contract { aborts_if accumulated_rewards * staking_contract.commission_percentage > MAX_U64; } - spec schema IncreaseLockupWithCapAbortsIf{ + spec schema IncreaseLockupWithCapAbortsIf { use aptos_framework::timestamp; staker: address; operator: address; @@ -514,7 +514,9 @@ spec aptos_framework::staking_contract { let config = global(@aptos_framework); let stake_pool = global(pool_address); let old_locked_until_secs = stake_pool.locked_until_secs; - let seconds = global(@aptos_framework).microseconds / timestamp::MICRO_CONVERSION_FACTOR; + let seconds = global( + @aptos_framework + ).microseconds / timestamp::MICRO_CONVERSION_FACTOR; let new_locked_until_secs = seconds + config.recurring_lockup_duration_secs; aborts_if seconds + config.recurring_lockup_duration_secs > MAX_U64; aborts_if old_locked_until_secs > new_locked_until_secs || old_locked_until_secs == new_locked_until_secs; @@ -573,7 +575,9 @@ spec aptos_framework::staking_contract { spec schema PreconditionsInCreateContract { requires exists(@aptos_framework); requires exists(@aptos_framework); - requires exists(@aptos_framework) || !std::features::spec_periodical_reward_rate_decrease_enabled(); + requires exists( + @aptos_framework + ) || !std::features::spec_periodical_reward_rate_decrease_enabled(); requires exists(@aptos_framework); requires exists(@aptos_framework); requires exists(@aptos_framework); @@ -587,7 +591,9 @@ spec aptos_framework::staking_contract { // postconditions account::create_resource_account() let acc = global(resource_addr); - aborts_if exists(resource_addr) && (len(acc.signer_capability_offer.for.vec) != 0 || acc.sequence_number != 0); + aborts_if exists(resource_addr) && (len( + acc.signer_capability_offer.for.vec + ) != 0 || acc.sequence_number != 0); aborts_if !exists(resource_addr) && len(bcs::to_bytes(resource_addr)) != 32; aborts_if len(account::ZERO_AUTH_KEY) != 32; @@ -598,6 +604,8 @@ spec aptos_framework::staking_contract { aborts_if exists(resource_addr); aborts_if exists(resource_addr); // 12 is the times that calls 'events::guids' - aborts_if exists(resource_addr) && acc.guid_creation_num + 12 >= account::MAX_GUID_CREATION_NUM; + aborts_if exists( + resource_addr + ) && acc.guid_creation_num + 12 >= account::MAX_GUID_CREATION_NUM; } } diff --git a/aptos-move/framework/aptos-framework/sources/vesting.move b/aptos-move/framework/aptos-framework/sources/vesting.move index 3ada2da7f8615..527b4726ffb3b 100644 --- a/aptos-move/framework/aptos-framework/sources/vesting.move +++ b/aptos-move/framework/aptos-framework/sources/vesting.move @@ -48,7 +48,7 @@ module aptos_framework::vesting { use aptos_framework::aptos_account::{Self, assert_account_is_registered_for_apt}; use aptos_framework::aptos_coin::AptosCoin; use aptos_framework::coin::{Self, Coin}; - use aptos_framework::event::{EventHandle, emit_event}; + use aptos_framework::event::{EventHandle, emit, emit_event}; use aptos_framework::stake; use aptos_framework::staking_contract; use aptos_framework::system_addresses; @@ -170,6 +170,90 @@ module aptos_framework::vesting { create_events: EventHandle, } + #[event] + struct CreateVestingContract has drop, store { + operator: address, + voter: address, + grant_amount: u64, + withdrawal_address: address, + vesting_contract_address: address, + staking_pool_address: address, + commission_percentage: u64, + } + + #[event] + struct UpdateOperator has drop, store { + admin: address, + vesting_contract_address: address, + staking_pool_address: address, + old_operator: address, + new_operator: address, + commission_percentage: u64, + } + + #[event] + struct UpdateVoter has drop, store { + admin: address, + vesting_contract_address: address, + staking_pool_address: address, + old_voter: address, + new_voter: address, + } + + #[event] + struct ResetLockup has drop, store { + admin: address, + vesting_contract_address: address, + staking_pool_address: address, + new_lockup_expiration_secs: u64, + } + + #[event] + struct SetBeneficiary has drop, store { + admin: address, + vesting_contract_address: address, + shareholder: address, + old_beneficiary: address, + new_beneficiary: address, + } + + #[event] + struct UnlockRewards has drop, store { + admin: address, + vesting_contract_address: address, + staking_pool_address: address, + amount: u64, + } + + #[event] + struct Vest has drop, store { + admin: address, + vesting_contract_address: address, + staking_pool_address: address, + period_vested: u64, + amount: u64, + } + + #[event] + struct Distribute has drop, store { + admin: address, + vesting_contract_address: address, + amount: u64, + } + + #[event] + struct Terminate has drop, store { + admin: address, + vesting_contract_address: address, + } + + #[event] + struct AdminWithdraw has drop, store { + admin: address, + vesting_contract_address: address, + amount: u64, + } + struct CreateVestingContractEvent has drop, store { operator: address, voter: address, @@ -393,7 +477,10 @@ module aptos_framework::vesting { /// address is actually a shareholder address, just return the address back. /// /// This returns 0x0 if no shareholder is found for the given beneficiary / the address is not a shareholder itself. - public fun shareholder(vesting_contract_address: address, shareholder_or_beneficiary: address): address acquires VestingContract { + public fun shareholder( + vesting_contract_address: address, + shareholder_or_beneficiary: address + ): address acquires VestingContract { assert_active_vesting_contract(vesting_contract_address); let shareholders = &shareholders(vesting_contract_address); @@ -497,6 +584,19 @@ module aptos_framework::vesting { let contract_address = signer::address_of(&contract_signer); let admin_store = borrow_global_mut(admin_address); vector::push_back(&mut admin_store.vesting_contracts, contract_address); + if (std::features::module_event_migration_enabled()) { + emit( + CreateVestingContract { + operator, + voter, + withdrawal_address, + grant_amount, + vesting_contract_address: contract_address, + staking_pool_address: pool_address, + commission_percentage, + }, + ); + }; emit_event( &mut admin_store.create_events, CreateVestingContractEvent { @@ -595,6 +695,17 @@ module aptos_framework::vesting { vesting_schedule.last_vested_period = next_period_to_vest; unlock_stake(vesting_contract, vested_amount); + if (std::features::module_event_migration_enabled()) { + emit( + Vest { + admin: vesting_contract.admin, + vesting_contract_address: contract_address, + staking_pool_address: vesting_contract.staking.pool_address, + period_vested: next_period_to_vest, + amount: vested_amount, + }, + ); + }; emit_event( &mut vesting_contract.vest_events, VestEvent { @@ -650,6 +761,15 @@ module aptos_framework::vesting { coin::destroy_zero(coins); }; + if (std::features::module_event_migration_enabled()) { + emit( + Distribute { + admin: vesting_contract.admin, + vesting_contract_address: contract_address, + amount: total_distribution_amount, + }, + ); + }; emit_event( &mut vesting_contract.distribute_events, DistributeEvent { @@ -689,6 +809,14 @@ module aptos_framework::vesting { vesting_contract.remaining_grant = 0; unlock_stake(vesting_contract, active_stake); + if (std::features::module_event_migration_enabled()) { + emit( + Terminate { + admin: vesting_contract.admin, + vesting_contract_address: contract_address, + }, + ); + }; emit_event( &mut vesting_contract.terminate_events, TerminateEvent { @@ -702,7 +830,10 @@ module aptos_framework::vesting { /// has already been terminated. public entry fun admin_withdraw(admin: &signer, contract_address: address) acquires VestingContract { let vesting_contract = borrow_global(contract_address); - assert!(vesting_contract.state == VESTING_POOL_TERMINATED, error::invalid_state(EVESTING_CONTRACT_STILL_ACTIVE)); + assert!( + vesting_contract.state == VESTING_POOL_TERMINATED, + error::invalid_state(EVESTING_CONTRACT_STILL_ACTIVE) + ); let vesting_contract = borrow_global_mut(contract_address); verify_admin(admin, vesting_contract); @@ -714,6 +845,15 @@ module aptos_framework::vesting { }; aptos_account::deposit_coins(vesting_contract.withdrawal_address, coins); + if (std::features::module_event_migration_enabled()) { + emit( + AdminWithdraw { + admin: vesting_contract.admin, + vesting_contract_address: contract_address, + amount, + }, + ); + }; emit_event( &mut vesting_contract.admin_withdraw_events, AdminWithdrawEvent { @@ -738,6 +878,18 @@ module aptos_framework::vesting { vesting_contract.staking.operator = new_operator; vesting_contract.staking.commission_percentage = commission_percentage; + if (std::features::module_event_migration_enabled()) { + emit( + UpdateOperator { + admin: vesting_contract.admin, + vesting_contract_address: contract_address, + staking_pool_address: vesting_contract.staking.pool_address, + old_operator, + new_operator, + commission_percentage, + }, + ); + }; emit_event( &mut vesting_contract.update_operator_events, UpdateOperatorEvent { @@ -787,6 +939,17 @@ module aptos_framework::vesting { staking_contract::update_voter(contract_signer, vesting_contract.staking.operator, new_voter); vesting_contract.staking.voter = new_voter; + if (std::features::module_event_migration_enabled()) { + emit( + UpdateVoter { + admin: vesting_contract.admin, + vesting_contract_address: contract_address, + staking_pool_address: vesting_contract.staking.pool_address, + old_voter, + new_voter, + }, + ); + }; emit_event( &mut vesting_contract.update_voter_events, UpdateVoterEvent { @@ -808,6 +971,16 @@ module aptos_framework::vesting { let contract_signer = &get_vesting_account_signer_internal(vesting_contract); staking_contract::reset_lockup(contract_signer, vesting_contract.staking.operator); + if (std::features::module_event_migration_enabled()) { + emit( + ResetLockup { + admin: vesting_contract.admin, + vesting_contract_address: contract_address, + staking_pool_address: vesting_contract.staking.pool_address, + new_lockup_expiration_secs: stake::get_lockup_secs(vesting_contract.staking.pool_address), + }, + ); + }; emit_event( &mut vesting_contract.reset_lockup_events, ResetLockupEvent { @@ -841,6 +1014,17 @@ module aptos_framework::vesting { simple_map::add(beneficiaries, shareholder, new_beneficiary); }; + if (std::features::module_event_migration_enabled()) { + emit( + SetBeneficiary { + admin: vesting_contract.admin, + vesting_contract_address: contract_address, + shareholder, + old_beneficiary, + new_beneficiary, + }, + ); + }; emit_event( &mut vesting_contract.set_beneficiary_events, SetBeneficiaryEvent { @@ -1029,7 +1213,16 @@ module aptos_framework::vesting { public fun setup(aptos_framework: &signer, accounts: &vector
) { use aptos_framework::aptos_account::create_account; - stake::initialize_for_test_custom(aptos_framework, MIN_STAKE, GRANT_AMOUNT * 10, 3600, true, 10, 10000, 1000000); + stake::initialize_for_test_custom( + aptos_framework, + MIN_STAKE, + GRANT_AMOUNT * 10, + 3600, + true, + 10, + 10000, + 1000000 + ); vector::for_each_ref(accounts, |addr| { let addr: address = *addr; @@ -1413,7 +1606,13 @@ module aptos_framework::vesting { // Distribution should pay commission to operator first and remaining amount to shareholders. stake::fast_forward_to_unlock(stake_pool_address); - stake::assert_stake_pool(stake_pool_address, with_rewards(GRANT_AMOUNT), with_rewards(accumulated_rewards), 0, 0); + stake::assert_stake_pool( + stake_pool_address, + with_rewards(GRANT_AMOUNT), + with_rewards(accumulated_rewards), + 0, + 0 + ); // Operator also earns more commission from the rewards earnt on the withdrawn rewards. let commission_on_staker_rewards = (with_rewards(staker_rewards) - staker_rewards) / 10; staker_rewards = with_rewards(staker_rewards) - commission_on_staker_rewards; @@ -1464,7 +1663,13 @@ module aptos_framework::vesting { // Distribution should pay commission to operator first and remaining amount to shareholders. stake::fast_forward_to_unlock(stake_pool_address); - stake::assert_stake_pool(stake_pool_address, with_rewards(GRANT_AMOUNT), with_rewards(accumulated_rewards), 0, 0); + stake::assert_stake_pool( + stake_pool_address, + with_rewards(GRANT_AMOUNT), + with_rewards(accumulated_rewards), + 0, + 0 + ); // Operator also earns more commission from the rewards earnt on the withdrawn rewards. let commission_on_staker_rewards = (with_rewards(staker_rewards) - staker_rewards) / 10; staker_rewards = with_rewards(staker_rewards) - commission_on_staker_rewards; @@ -1519,7 +1724,10 @@ module aptos_framework::vesting { // Stake pool earns some rewards. stake::end_epoch(); - let (_, accumulated_rewards, _) = staking_contract::staking_contract_amounts(contract_address, operator_address); + let (_, accumulated_rewards, _) = staking_contract::staking_contract_amounts( + contract_address, + operator_address + ); // Update commission percentage to 20%. This also immediately requests commission. update_commission_percentage(admin, contract_address, 20); @@ -1532,7 +1740,10 @@ module aptos_framework::vesting { // Stake pool earns some more rewards. stake::end_epoch(); - let (_, accumulated_rewards, _) = staking_contract::staking_contract_amounts(contract_address, operator_address); + let (_, accumulated_rewards, _) = staking_contract::staking_contract_amounts( + contract_address, + operator_address + ); // Request commission again. staking_contract::request_commission(operator, contract_address, operator_address); @@ -1550,7 +1761,14 @@ module aptos_framework::vesting { assert!(coin::balance(operator_address) == expected_commission, 1); } - #[test(aptos_framework = @0x1, admin = @0x123, shareholder = @0x234, operator1 = @0x345, beneficiary = @0x456, operator2 = @0x567)] + #[test( + aptos_framework = @0x1, + admin = @0x123, + shareholder = @0x234, + operator1 = @0x345, + beneficiary = @0x456, + operator2 = @0x567 + )] public entry fun test_set_beneficiary_for_operator( aptos_framework: &signer, admin: &signer, @@ -1626,7 +1844,6 @@ module aptos_framework::vesting { // Assert that the rewards go to operator2, and the balance of the operator1's beneficiay remains the same. assert!(coin::balance(operator_address2) >= expected_commission, 1); assert!(coin::balance(beneficiary_address) == old_beneficiay_balance, 1); - } #[test(aptos_framework = @0x1, admin = @0x123, shareholder = @0x234)] diff --git a/aptos-move/framework/aptos-framework/sources/voting.move b/aptos-move/framework/aptos-framework/sources/voting.move index 299df8685d721..3bc26528ba736 100644 --- a/aptos-move/framework/aptos-framework/sources/voting.move +++ b/aptos-move/framework/aptos-framework/sources/voting.move @@ -139,7 +139,8 @@ module aptos_framework::voting { vote_events: EventHandle, } - struct CreateProposalEvent has drop, store { + #[event] + struct CreateProposal has drop, store { proposal_id: u64, early_resolution_vote_threshold: Option, execution_hash: vector, @@ -148,16 +149,19 @@ module aptos_framework::voting { min_vote_threshold: u128, } - struct RegisterForumEvent has drop, store { + #[event] + struct RegisterForum has drop, store { hosting_account: address, proposal_type_info: TypeInfo, } - struct VoteEvent has drop, store { + #[event] + struct Vote has drop, store { proposal_id: u64, num_votes: u64, } + #[event] struct ResolveProposal has drop, store { proposal_id: u64, yes_votes: u128, @@ -165,6 +169,25 @@ module aptos_framework::voting { resolved_early: bool } + struct CreateProposalEvent has drop, store { + proposal_id: u64, + early_resolution_vote_threshold: Option, + execution_hash: vector, + expiration_secs: u64, + metadata: SimpleMap>, + min_vote_threshold: u128, + } + + struct RegisterForumEvent has drop, store { + hosting_account: address, + proposal_type_info: TypeInfo, + } + + struct VoteEvent has drop, store { + proposal_id: u64, + num_votes: u64, + } + public fun register(account: &signer) { let addr = signer::address_of(account); assert!(!exists>(addr), error::already_exists(EVOTING_FORUM_ALREADY_REGISTERED)); @@ -180,6 +203,14 @@ module aptos_framework::voting { } }; + if (std::features::module_event_migration_enabled()) { + event::emit( + RegisterForum { + hosting_account: addr, + proposal_type_info: type_info::type_of(), + }, + ); + }; event::emit_event( &mut voting_forum.events.register_forum_events, RegisterForumEvent { @@ -272,8 +303,8 @@ module aptos_framework::voting { // This value is by default false. We turn this value to true when we start executing the multi-step proposal. This value // will be used to disable further voting after we started executing the multi-step proposal. simple_map::add(&mut metadata, is_multi_step_in_execution_key, to_bytes(&false)); - // If the proposal is a single-step proposal, we check if the metadata passed by the client has the IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY key. - // If they have the key, we will remove it, because a single-step proposal that doesn't need this key. + // If the proposal is a single-step proposal, we check if the metadata passed by the client has the IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY key. + // If they have the key, we will remove it, because a single-step proposal that doesn't need this key. } else if (simple_map::contains_key(&mut metadata, &is_multi_step_in_execution_key)) { simple_map::remove(&mut metadata, &is_multi_step_in_execution_key); }; @@ -293,6 +324,18 @@ module aptos_framework::voting { resolution_time_secs: 0, }); + if (std::features::module_event_migration_enabled()) { + event::emit( + CreateProposal { + proposal_id, + early_resolution_vote_threshold, + execution_hash, + expiration_secs, + metadata, + min_vote_threshold, + }, + ); + }; event::emit_event( &mut voting_forum.events.create_proposal_events, CreateProposalEvent { @@ -334,8 +377,10 @@ module aptos_framework::voting { assert!(!proposal.is_resolved, error::invalid_state(EPROPOSAL_ALREADY_RESOLVED)); // Assert this proposal is single-step, or if the proposal is multi-step, it is not in execution yet. assert!(!simple_map::contains_key(&proposal.metadata, &utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY)) - || *simple_map::borrow(&proposal.metadata, &utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY)) == to_bytes(&false), - error::invalid_state(EMULTI_STEP_PROPOSAL_IN_EXECUTION)); + || *simple_map::borrow(&proposal.metadata, &utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY)) == to_bytes( + &false + ), + error::invalid_state(EMULTI_STEP_PROPOSAL_IN_EXECUTION)); if (should_pass) { proposal.yes_votes = proposal.yes_votes + (num_votes as u128); @@ -352,6 +397,9 @@ module aptos_framework::voting { simple_map::add(&mut proposal.metadata, key, timestamp_secs_bytes); }; + if (std::features::module_event_migration_enabled()) { + event::emit(Vote { proposal_id, num_votes }); + }; event::emit_event( &mut voting_forum.events.vote_events, VoteEvent { proposal_id, num_votes }, @@ -400,13 +448,26 @@ module aptos_framework::voting { let has_multi_step_key = simple_map::contains_key(&proposal.metadata, &multi_step_key); if (has_multi_step_key) { let is_multi_step_proposal = from_bcs::to_bool(*simple_map::borrow(&proposal.metadata, &multi_step_key)); - assert!(!is_multi_step_proposal, error::permission_denied(EMULTI_STEP_PROPOSAL_CANNOT_USE_SINGLE_STEP_RESOLVE_FUNCTION)); + assert!( + !is_multi_step_proposal, + error::permission_denied(EMULTI_STEP_PROPOSAL_CANNOT_USE_SINGLE_STEP_RESOLVE_FUNCTION) + ); }; let resolved_early = can_be_resolved_early(proposal); proposal.is_resolved = true; proposal.resolution_time_secs = timestamp::now_seconds(); + if (std::features::module_event_migration_enabled()) { + event::emit( + ResolveProposal { + proposal_id, + yes_votes: proposal.yes_votes, + no_votes: proposal.no_votes, + resolved_early, + }, + ); + }; event::emit_event( &mut voting_forum.events.resolve_proposal_events, ResolveProposal { @@ -441,16 +502,24 @@ module aptos_framework::voting { // Update the IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY key to indicate that the multi-step proposal is in execution. let multi_step_in_execution_key = utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY); if (simple_map::contains_key(&proposal.metadata, &multi_step_in_execution_key)) { - let is_multi_step_proposal_in_execution_value = simple_map::borrow_mut(&mut proposal.metadata, &multi_step_in_execution_key); + let is_multi_step_proposal_in_execution_value = simple_map::borrow_mut( + &mut proposal.metadata, + &multi_step_in_execution_key + ); *is_multi_step_proposal_in_execution_value = to_bytes(&true); }; let multi_step_key = utf8(IS_MULTI_STEP_PROPOSAL_KEY); - let is_multi_step = simple_map::contains_key(&proposal.metadata, &multi_step_key) && from_bcs::to_bool(*simple_map::borrow(&proposal.metadata, &multi_step_key)); + let is_multi_step = simple_map::contains_key(&proposal.metadata, &multi_step_key) && from_bcs::to_bool( + *simple_map::borrow(&proposal.metadata, &multi_step_key) + ); let next_execution_hash_is_empty = vector::length(&next_execution_hash) == 0; // Assert that if this proposal is single-step, the `next_execution_hash` parameter is empty. - assert!(is_multi_step || next_execution_hash_is_empty, error::invalid_argument(ESINGLE_STEP_PROPOSAL_CANNOT_HAVE_NEXT_EXECUTION_HASH)); + assert!( + is_multi_step || next_execution_hash_is_empty, + error::invalid_argument(ESINGLE_STEP_PROPOSAL_CANNOT_HAVE_NEXT_EXECUTION_HASH) + ); // If the `next_execution_hash` parameter is empty, it means that either // - this proposal is a single-step proposal, or @@ -462,7 +531,10 @@ module aptos_framework::voting { // Set the `IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY` value to false upon successful resolution of the last step of a multi-step proposal. if (is_multi_step) { - let is_multi_step_proposal_in_execution_value = simple_map::borrow_mut(&mut proposal.metadata, &multi_step_in_execution_key); + let is_multi_step_proposal_in_execution_value = simple_map::borrow_mut( + &mut proposal.metadata, + &multi_step_in_execution_key + ); *is_multi_step_proposal_in_execution_value = to_bytes(&false); }; } else { @@ -475,7 +547,17 @@ module aptos_framework::voting { // For multi-step proposals, we emit one `ResolveProposal` event per step in the multi-step proposal. This means // that we emit multiple `ResolveProposal` events for the same multi-step proposal. let resolved_early = can_be_resolved_early(proposal); - event::emit_event( + if (std::features::module_event_migration_enabled()) { + event::emit( + ResolveProposal { + proposal_id, + yes_votes: proposal.yes_votes, + no_votes: proposal.no_votes, + resolved_early, + }, + ); + }; + event::emit_event( &mut voting_forum.events.resolve_proposal_events, ResolveProposal { proposal_id, @@ -484,23 +566,30 @@ module aptos_framework::voting { resolved_early, }, ); + } #[view] /// Return the next unassigned proposal id - public fun next_proposal_id(voting_forum_address: address,): u64 acquires VotingForum { + public fun next_proposal_id(voting_forum_address: address, ): u64 acquires VotingForum { let voting_forum = borrow_global>(voting_forum_address); voting_forum.next_proposal_id } #[view] - public fun get_proposer(voting_forum_address: address, proposal_id: u64): address acquires VotingForum { + public fun get_proposer( + voting_forum_address: address, + proposal_id: u64 + ): address acquires VotingForum { let proposal = get_proposal(voting_forum_address, proposal_id); proposal.proposer } #[view] - public fun is_voting_closed(voting_forum_address: address, proposal_id: u64): bool acquires VotingForum { + public fun is_voting_closed( + voting_forum_address: address, + proposal_id: u64 + ): bool acquires VotingForum { let proposal = get_proposal(voting_forum_address, proposal_id); can_be_resolved_early(proposal) || is_voting_period_over(proposal) } @@ -648,7 +737,10 @@ module aptos_framework::voting { let voting_forum = borrow_global>(voting_forum_address); let proposal = table::borrow(&voting_forum.proposals, proposal_id); let is_multi_step_in_execution_key = utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY); - assert!(simple_map::contains_key(&proposal.metadata, &is_multi_step_in_execution_key), error::invalid_argument(EPROPOSAL_IS_SINGLE_STEP)); + assert!( + simple_map::contains_key(&proposal.metadata, &is_multi_step_in_execution_key), + error::invalid_argument(EPROPOSAL_IS_SINGLE_STEP) + ); from_bcs::to_bool(*simple_map::borrow(&proposal.metadata, &is_multi_step_in_execution_key)) } @@ -714,7 +806,12 @@ module aptos_framework::voting { } #[test_only] - public fun resolve_proposal_for_test(voting_forum_address: address, proposal_id: u64, is_multi_step: bool, finish_multi_step_execution: bool) acquires VotingForum { + public fun resolve_proposal_for_test( + voting_forum_address: address, + proposal_id: u64, + is_multi_step: bool, + finish_multi_step_execution: bool + ) acquires VotingForum { if (is_multi_step) { let execution_hash = vector::empty(); vector::push_back(&mut execution_hash, 1); @@ -738,7 +835,10 @@ module aptos_framework::voting { } #[test_only] - public fun create_proposal_with_empty_execution_hash_should_fail_generic(governance: &signer, is_multi_step: bool) acquires VotingForum { + public fun create_proposal_with_empty_execution_hash_should_fail_generic( + governance: &signer, + is_multi_step: bool + ) acquires VotingForum { account::create_account_for_test(@aptos_framework); let governance_address = signer::address_of(governance); account::create_account_for_test(governance_address); @@ -780,12 +880,19 @@ module aptos_framework::voting { #[test(governance = @0x123)] #[expected_failure(abort_code = 0x10004, location = Self)] - public fun create_proposal_with_empty_execution_hash_should_fail_multi_step(governance: &signer) acquires VotingForum { + public fun create_proposal_with_empty_execution_hash_should_fail_multi_step( + governance: &signer + ) acquires VotingForum { create_proposal_with_empty_execution_hash_should_fail_generic(governance, true); } #[test_only] - public entry fun test_voting_passed_generic(aptos_framework: &signer, governance: &signer, use_create_multi_step: bool, use_resolve_multi_step: bool) acquires VotingForum { + public entry fun test_voting_passed_generic( + aptos_framework: &signer, + governance: &signer, + use_create_multi_step: bool, + use_resolve_multi_step: bool + ) acquires VotingForum { account::create_account_for_test(@aptos_framework); timestamp::set_time_has_started_for_testing(aptos_framework); @@ -827,18 +934,28 @@ module aptos_framework::voting { } #[test(aptos_framework = @aptos_framework, governance = @0x123)] - #[expected_failure(abort_code=0x5000a, location = Self)] - public entry fun test_voting_passed_multi_step_cannot_use_single_step_resolve_function(aptos_framework: &signer, governance: &signer) acquires VotingForum { + #[expected_failure(abort_code = 0x5000a, location = Self)] + public entry fun test_voting_passed_multi_step_cannot_use_single_step_resolve_function( + aptos_framework: &signer, + governance: &signer + ) acquires VotingForum { test_voting_passed_generic(aptos_framework, governance, true, false); } #[test(aptos_framework = @aptos_framework, governance = @0x123)] - public entry fun test_voting_passed_single_step_can_use_generic_function(aptos_framework: &signer, governance: &signer) acquires VotingForum { + public entry fun test_voting_passed_single_step_can_use_generic_function( + aptos_framework: &signer, + governance: &signer + ) acquires VotingForum { test_voting_passed_generic(aptos_framework, governance, false, true); } #[test_only] - public entry fun test_cannot_resolve_twice_generic(aptos_framework: &signer, governance: &signer, is_multi_step: bool) acquires VotingForum { + public entry fun test_cannot_resolve_twice_generic( + aptos_framework: &signer, + governance: &signer, + is_multi_step: bool + ) acquires VotingForum { account::create_account_for_test(@aptos_framework); timestamp::set_time_has_started_for_testing(aptos_framework); @@ -868,12 +985,19 @@ module aptos_framework::voting { #[test(aptos_framework = @aptos_framework, governance = @0x123)] #[expected_failure(abort_code = 0x30003, location = Self)] - public entry fun test_cannot_resolve_twice_multi_step(aptos_framework: &signer, governance: &signer) acquires VotingForum { + public entry fun test_cannot_resolve_twice_multi_step( + aptos_framework: &signer, + governance: &signer + ) acquires VotingForum { test_cannot_resolve_twice_generic(aptos_framework, governance, true); } #[test_only] - public entry fun test_voting_passed_early_generic(aptos_framework: &signer, governance: &signer, is_multi_step: bool) acquires VotingForum { + public entry fun test_voting_passed_early_generic( + aptos_framework: &signer, + governance: &signer, + is_multi_step: bool + ) acquires VotingForum { account::create_account_for_test(@aptos_framework); timestamp::set_time_has_started_for_testing(aptos_framework); @@ -926,7 +1050,10 @@ module aptos_framework::voting { } #[test(aptos_framework = @aptos_framework, governance = @0x123)] - public entry fun test_voting_passed_early_multi_step(aptos_framework: &signer, governance: &signer) acquires VotingForum { + public entry fun test_voting_passed_early_multi_step( + aptos_framework: &signer, + governance: &signer + ) acquires VotingForum { test_voting_passed_early_generic(aptos_framework, governance, true); } @@ -969,7 +1096,11 @@ module aptos_framework::voting { } #[test_only] - public entry fun test_voting_failed_generic(aptos_framework: &signer, governance: &signer, is_multi_step: bool) acquires VotingForum { + public entry fun test_voting_failed_generic( + aptos_framework: &signer, + governance: &signer, + is_multi_step: bool + ) acquires VotingForum { account::create_account_for_test(@aptos_framework); timestamp::set_time_has_started_for_testing(aptos_framework); @@ -1021,7 +1152,7 @@ module aptos_framework::voting { } #[test(aptos_framework = @aptos_framework, governance = @0x123)] - #[expected_failure(abort_code=0x30009, location = Self)] + #[expected_failure(abort_code = 0x30009, location = Self)] public entry fun test_cannot_vote_after_multi_step_proposal_starts_executing( aptos_framework: signer, governance: signer @@ -1048,7 +1179,11 @@ module aptos_framework::voting { } #[test_only] - public entry fun test_voting_failed_early_generic(aptos_framework: &signer, governance: &signer, is_multi_step: bool) acquires VotingForum { + public entry fun test_voting_failed_early_generic( + aptos_framework: &signer, + governance: &signer, + is_multi_step: bool + ) acquires VotingForum { account::create_account_for_test(@aptos_framework); timestamp::set_time_has_started_for_testing(aptos_framework); @@ -1077,7 +1212,10 @@ module aptos_framework::voting { #[test(aptos_framework = @aptos_framework, governance = @0x123)] #[expected_failure(abort_code = 0x30002, location = Self)] - public entry fun test_voting_failed_early_multi_step(aptos_framework: &signer, governance: &signer) acquires VotingForum { + public entry fun test_voting_failed_early_multi_step( + aptos_framework: &signer, + governance: &signer + ) acquires VotingForum { test_voting_failed_early_generic(aptos_framework, governance, false); } diff --git a/aptos-move/framework/aptos-token-objects/doc/collection.md b/aptos-move/framework/aptos-token-objects/doc/collection.md index bbe8f7ec3daab..e5e482366a12d 100644 --- a/aptos-move/framework/aptos-token-objects/doc/collection.md +++ b/aptos-move/framework/aptos-token-objects/doc/collection.md @@ -1114,6 +1114,16 @@ increment_concurrent_supply cannot be used until AGGREGATOR_API_V2 is enabled. supply.current_supply <= supply.max_supply, error::out_of_range(ECOLLECTION_SUPPLY_EXCEEDED), ); + + if (std::features::module_event_migration_enabled()) { + event::emit( + Mint { + collection: collection_addr, + index: aggregator_v2::create_snapshot(supply.total_minted), + token, + }, + ); + }; event::emit_event(&mut supply.mint_events, MintEvent { index: supply.total_minted, @@ -1125,6 +1135,15 @@ increment_concurrent_supply cannot be used until AGGREGATOR_API_V2 is enabled. let supply = borrow_global_mut<UnlimitedSupply>(collection_addr); supply.current_supply = supply.current_supply + 1; supply.total_minted = supply.total_minted + 1; + if (std::features::module_event_migration_enabled()) { + event::emit( + Mint { + collection: collection_addr, + index: aggregator_v2::create_snapshot(supply.total_minted), + token, + }, + ); + }; event::emit_event( &mut supply.mint_events, MintEvent { @@ -1189,7 +1208,15 @@ Called by token on mint to increment supply if there's an appropriate Supply str supply.current_supply <= supply.max_supply, error::out_of_range(ECOLLECTION_SUPPLY_EXCEEDED), ); - // TODO[agg_v2](cleanup): Update to Mint in the future release + if (std::features::module_event_migration_enabled()) { + event::emit( + Mint { + collection: collection_addr, + index: aggregator_v2::create_snapshot(supply.total_minted), + token, + }, + ); + }; event::emit_event(&mut supply.mint_events, MintEvent { index: supply.total_minted, @@ -1201,7 +1228,15 @@ Called by token on mint to increment supply if there's an appropriate Supply str let supply = borrow_global_mut<UnlimitedSupply>(collection_addr); supply.current_supply = supply.current_supply + 1; supply.total_minted = supply.total_minted + 1; - // TODO[agg_v2](cleanup): Update to Mint in the future release + if (std::features::module_event_migration_enabled()) { + event::emit( + Mint { + collection: collection_addr, + index: aggregator_v2::create_snapshot(supply.total_minted), + token, + }, + ); + }; event::emit_event( &mut supply.mint_events, MintEvent { @@ -1258,7 +1293,16 @@ Called by token on burn to decrement supply if there's an appropriate Supply str } else if (exists<FixedSupply>(collection_addr)) { let supply = borrow_global_mut<FixedSupply>(collection_addr); supply.current_supply = supply.current_supply - 1; - // TODO[agg_v2](cleanup): Update to Burn in the future release + if (std::features::module_event_migration_enabled()) { + event::emit( + Burn { + collection: collection_addr, + index: *option::borrow(&index), + token, + previous_owner, + }, + ); + }; event::emit_event( &mut supply.burn_events, BurnEvent { @@ -1269,7 +1313,16 @@ Called by token on burn to decrement supply if there's an appropriate Supply str } else if (exists<UnlimitedSupply>(collection_addr)) { let supply = borrow_global_mut<UnlimitedSupply>(collection_addr); supply.current_supply = supply.current_supply - 1; - // TODO[agg_v2](cleanup): Update to Burn in the future release + if (std::features::module_event_migration_enabled()) { + event::emit( + Burn { + collection: collection_addr, + index: *option::borrow(&index), + token, + previous_owner, + }, + ); + }; event::emit_event( &mut supply.burn_events, BurnEvent { @@ -1333,7 +1386,9 @@ Creates a MutatorRef, which gates the ability to mutate any fields that support let metadata_object_signer = object::generate_signer_for_extending(ref); assert!(features::concurrent_token_v2_enabled(), error::invalid_argument(ECONCURRENT_NOT_ENABLED)); - let (supply, current_supply, total_minted, burn_events, mint_events) = if (exists<FixedSupply>(metadata_object_address)) { + let (supply, current_supply, total_minted, burn_events, mint_events) = if (exists<FixedSupply>( + metadata_object_address + )) { let FixedSupply { current_supply, max_supply, @@ -1452,7 +1507,9 @@ it from being parallelized. Implementation -
public fun count<T: key>(collection: Object<T>): Option<u64> acquires FixedSupply, UnlimitedSupply, ConcurrentSupply {
+
public fun count<T: key>(
+    collection: Object<T>
+): Option<u64> acquires FixedSupply, UnlimitedSupply, ConcurrentSupply {
     let collection_address = object::object_address(&collection);
     check_collection_exists(collection_address);
 
@@ -1622,14 +1679,13 @@ Once the collection has been created, the collection address should be saved for
 
public fun set_name(mutator_ref: &MutatorRef, name: String) acquires Collection {
     assert!(string::length(&name) <= MAX_COLLECTION_NAME_LENGTH, error::out_of_range(ECOLLECTION_NAME_TOO_LONG));
     let collection = borrow_mut(mutator_ref);
-    let old_name = collection.name;
-    collection.name = name;
     event::emit(Mutation {
         mutated_field_name: string::utf8(b"name") ,
         collection: object::address_to_object(mutator_ref.self),
-        old_value: old_name,
+        old_value: collection.name,
         new_value: name,
     });
+    collection.name = name;
 }
 
@@ -1655,6 +1711,14 @@ Once the collection has been created, the collection address should be saved for
public fun set_description(mutator_ref: &MutatorRef, description: String) acquires Collection {
     assert!(string::length(&description) <= MAX_DESCRIPTION_LENGTH, error::out_of_range(EDESCRIPTION_TOO_LONG));
     let collection = borrow_mut(mutator_ref);
+    if (std::features::module_event_migration_enabled()) {
+        event::emit(Mutation {
+            mutated_field_name: string::utf8(b"description"),
+            collection: object::address_to_object(mutator_ref.self),
+            old_value: collection.description,
+            new_value: description,
+        });
+    };
     collection.description = description;
     event::emit_event(
         &mut collection.mutation_events,
@@ -1685,6 +1749,14 @@ Once the collection has been created, the collection address should be saved for
 
public fun set_uri(mutator_ref: &MutatorRef, uri: String) acquires Collection {
     assert!(string::length(&uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG));
     let collection = borrow_mut(mutator_ref);
+    if (std::features::module_event_migration_enabled()) {
+        event::emit(Mutation {
+            mutated_field_name: string::utf8(b"uri"),
+            collection: object::address_to_object(mutator_ref.self),
+            old_value: collection.uri,
+            new_value: uri,
+        });
+    };
     collection.uri = uri;
     event::emit_event(
         &mut collection.mutation_events,
diff --git a/aptos-move/framework/aptos-token-objects/doc/token.md b/aptos-move/framework/aptos-token-objects/doc/token.md
index 382c8f12e1f6f..069bf135ac4d1 100644
--- a/aptos-move/framework/aptos-token-objects/doc/token.md
+++ b/aptos-move/framework/aptos-token-objects/doc/token.md
@@ -16,6 +16,7 @@ token are:
 -  [Struct `BurnRef`](#0x4_token_BurnRef)
 -  [Struct `MutatorRef`](#0x4_token_MutatorRef)
 -  [Struct `MutationEvent`](#0x4_token_MutationEvent)
+-  [Struct `Mutation`](#0x4_token_Mutation)
 -  [Constants](#@Constants_0)
 -  [Function `create_common`](#0x4_token_create_common)
 -  [Function `create_token`](#0x4_token_create_token)
@@ -307,6 +308,52 @@ directly understand the behavior in a writeset.
 
 
 
+
+
+
+
+## Struct `Mutation`
+
+
+
+
#[event]
+struct Mutation has drop, store
+
+ + + +
+Fields + + +
+
+token_address: address +
+
+ +
+
+mutated_field_name: string::String +
+
+ +
+
+old_value: string::String +
+
+ +
+
+new_value: string::String +
+
+ +
+
+ +
@@ -449,7 +496,12 @@ The token name is over the maximum length ) { if (option::is_some(&name_with_index_suffix)) { // Be conservative, as we don't know what length the index will be, and assume worst case (20 chars in MAX_U64) - assert!(string::length(&name_prefix) + 20 + string::length(option::borrow(&name_with_index_suffix)) <= MAX_TOKEN_NAME_LENGTH, error::out_of_range(ETOKEN_NAME_TOO_LONG)); + assert!( + string::length(&name_prefix) + 20 + string::length( + option::borrow(&name_with_index_suffix) + ) <= MAX_TOKEN_NAME_LENGTH, + error::out_of_range(ETOKEN_NAME_TOO_LONG) + ); } else { assert!(string::length(&name_prefix) <= MAX_TOKEN_NAME_LENGTH, error::out_of_range(ETOKEN_NAME_TOO_LONG)); }; @@ -602,7 +654,16 @@ for additional specialization. ): ConstructorRef { let creator_address = signer::address_of(creator); let constructor_ref = object::create_object(creator_address); - create_common(&constructor_ref, creator_address, collection_name, description, name, option::none(), royalty, uri); + create_common( + &constructor_ref, + creator_address, + collection_name, + description, + name, + option::none(), + royalty, + uri + ); constructor_ref }
@@ -681,7 +742,16 @@ creating tokens in parallel, from the same collection, while providing sequentia ): ConstructorRef { let creator_address = signer::address_of(creator); let constructor_ref = object::create_object(creator_address); - create_common(&constructor_ref, creator_address, collection_name, description, name_with_index_prefix, option::some(name_with_index_suffix), royalty, uri); + create_common( + &constructor_ref, + creator_address, + collection_name, + description, + name_with_index_prefix, + option::some(name_with_index_suffix), + royalty, + uri + ); constructor_ref }
@@ -752,7 +822,16 @@ additional specialization. let seed = create_token_seed(&collection_name, &name); let constructor_ref = object::create_named_object(creator, seed); - create_common(&constructor_ref, creator_address, collection_name, description, name, option::none(), royalty, uri); + create_common( + &constructor_ref, + creator_address, + collection_name, + description, + name, + option::none(), + royalty, + uri + ); constructor_ref }
@@ -830,7 +909,16 @@ additional specialization. ): ConstructorRef { let creator_address = signer::address_of(creator); let constructor_ref = object::create_object_from_account(creator); - create_common(&constructor_ref, creator_address, collection_name, description, name, option::none(), royalty, uri); + create_common( + &constructor_ref, + creator_address, + collection_name, + description, + name, + option::none(), + royalty, + uri + ); constructor_ref }
@@ -1393,6 +1481,14 @@ as that would prohibit transactions to be executed in parallel.
public fun set_description(mutator_ref: &MutatorRef, description: String) acquires Token {
     assert!(string::length(&description) <= MAX_DESCRIPTION_LENGTH, error::out_of_range(EDESCRIPTION_TOO_LONG));
     let token = borrow_mut(mutator_ref);
+    if (std::features::module_event_migration_enabled()) {
+        event::emit(Mutation {
+            token_address: mutator_ref.self,
+            mutated_field_name: string::utf8(b"description"),
+            old_value: token.description,
+            new_value: description
+        })
+    };
     event::emit_event(
         &mut token.mutation_events,
         MutationEvent {
@@ -1440,6 +1536,14 @@ as that would prohibit transactions to be executed in parallel.
         old_name
     };
 
+    if (std::features::module_event_migration_enabled()) {
+        event::emit(Mutation {
+            token_address: mutator_ref.self,
+            mutated_field_name: string::utf8(b"name"),
+            old_value: old_name,
+            new_value: name
+        })
+    };
     event::emit_event(
         &mut token.mutation_events,
         MutationEvent {
@@ -1473,6 +1577,14 @@ as that would prohibit transactions to be executed in parallel.
 
public fun set_uri(mutator_ref: &MutatorRef, uri: String) acquires Token {
     assert!(string::length(&uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG));
     let token = borrow_mut(mutator_ref);
+    if (std::features::module_event_migration_enabled()) {
+        event::emit(Mutation {
+            token_address: mutator_ref.self,
+            mutated_field_name: string::utf8(b"uri"),
+            old_value: token.uri,
+            new_value: uri,
+        })
+    };
     event::emit_event(
         &mut token.mutation_events,
         MutationEvent {
diff --git a/aptos-move/framework/aptos-token-objects/sources/collection.move b/aptos-move/framework/aptos-token-objects/sources/collection.move
index 74ad95d9e3623..09634ba782e32 100644
--- a/aptos-move/framework/aptos-token-objects/sources/collection.move
+++ b/aptos-move/framework/aptos-token-objects/sources/collection.move
@@ -370,6 +370,16 @@ module aptos_token_objects::collection {
                 supply.current_supply <= supply.max_supply,
                 error::out_of_range(ECOLLECTION_SUPPLY_EXCEEDED),
             );
+
+            if (std::features::module_event_migration_enabled()) {
+                event::emit(
+                    Mint {
+                        collection: collection_addr,
+                        index: aggregator_v2::create_snapshot(supply.total_minted),
+                        token,
+                    },
+                );
+            };
             event::emit_event(&mut supply.mint_events,
                 MintEvent {
                     index: supply.total_minted,
@@ -381,6 +391,15 @@ module aptos_token_objects::collection {
             let supply = borrow_global_mut(collection_addr);
             supply.current_supply = supply.current_supply + 1;
             supply.total_minted = supply.total_minted + 1;
+            if (std::features::module_event_migration_enabled()) {
+                event::emit(
+                    Mint {
+                        collection: collection_addr,
+                        index: aggregator_v2::create_snapshot(supply.total_minted),
+                        token,
+                    },
+                );
+            };
             event::emit_event(
                 &mut supply.mint_events,
                 MintEvent {
@@ -425,7 +444,15 @@ module aptos_token_objects::collection {
                 supply.current_supply <= supply.max_supply,
                 error::out_of_range(ECOLLECTION_SUPPLY_EXCEEDED),
             );
-            // TODO[agg_v2](cleanup): Update to Mint in the future release
+            if (std::features::module_event_migration_enabled()) {
+                event::emit(
+                    Mint {
+                        collection: collection_addr,
+                        index: aggregator_v2::create_snapshot(supply.total_minted),
+                        token,
+                    },
+                );
+            };
             event::emit_event(&mut supply.mint_events,
                 MintEvent {
                     index: supply.total_minted,
@@ -437,7 +464,15 @@ module aptos_token_objects::collection {
             let supply = borrow_global_mut(collection_addr);
             supply.current_supply = supply.current_supply + 1;
             supply.total_minted = supply.total_minted + 1;
-            // TODO[agg_v2](cleanup): Update to Mint in the future release
+            if (std::features::module_event_migration_enabled()) {
+                event::emit(
+                    Mint {
+                        collection: collection_addr,
+                        index: aggregator_v2::create_snapshot(supply.total_minted),
+                        token,
+                    },
+                );
+            };
             event::emit_event(
                 &mut supply.mint_events,
                 MintEvent {
@@ -474,7 +509,16 @@ module aptos_token_objects::collection {
         } else if (exists(collection_addr)) {
             let supply = borrow_global_mut(collection_addr);
             supply.current_supply = supply.current_supply - 1;
-            // TODO[agg_v2](cleanup): Update to Burn in the future release
+            if (std::features::module_event_migration_enabled()) {
+                event::emit(
+                    Burn {
+                        collection: collection_addr,
+                        index: *option::borrow(&index),
+                        token,
+                        previous_owner,
+                    },
+                );
+            };
             event::emit_event(
                 &mut supply.burn_events,
                 BurnEvent {
@@ -485,7 +529,16 @@ module aptos_token_objects::collection {
         } else if (exists(collection_addr)) {
             let supply = borrow_global_mut(collection_addr);
             supply.current_supply = supply.current_supply - 1;
-            // TODO[agg_v2](cleanup): Update to Burn in the future release
+            if (std::features::module_event_migration_enabled()) {
+                event::emit(
+                    Burn {
+                        collection: collection_addr,
+                        index: *option::borrow(&index),
+                        token,
+                        previous_owner,
+                    },
+                );
+            };
             event::emit_event(
                 &mut supply.burn_events,
                 BurnEvent {
@@ -509,7 +562,9 @@ module aptos_token_objects::collection {
         let metadata_object_signer = object::generate_signer_for_extending(ref);
         assert!(features::concurrent_token_v2_enabled(), error::invalid_argument(ECONCURRENT_NOT_ENABLED));
 
-        let (supply, current_supply, total_minted, burn_events, mint_events) = if (exists(metadata_object_address)) {
+        let (supply, current_supply, total_minted, burn_events, mint_events) = if (exists(
+            metadata_object_address
+        )) {
             let FixedSupply {
                 current_supply,
                 max_supply,
@@ -570,7 +625,9 @@ module aptos_token_objects::collection {
     ///
     /// Note: Calling this method from transaction that also mints/burns, prevents
     /// it from being parallelized.
-    public fun count(collection: Object): Option acquires FixedSupply, UnlimitedSupply, ConcurrentSupply {
+    public fun count(
+        collection: Object
+    ): Option acquires FixedSupply, UnlimitedSupply, ConcurrentSupply {
         let collection_address = object::object_address(&collection);
         check_collection_exists(collection_address);
 
@@ -622,19 +679,26 @@ module aptos_token_objects::collection {
     public fun set_name(mutator_ref: &MutatorRef, name: String) acquires Collection {
         assert!(string::length(&name) <= MAX_COLLECTION_NAME_LENGTH, error::out_of_range(ECOLLECTION_NAME_TOO_LONG));
         let collection = borrow_mut(mutator_ref);
-        let old_name = collection.name;
-        collection.name = name;
         event::emit(Mutation {
             mutated_field_name: string::utf8(b"name") ,
             collection: object::address_to_object(mutator_ref.self),
-            old_value: old_name,
+            old_value: collection.name,
             new_value: name,
         });
+        collection.name = name;
     }
 
     public fun set_description(mutator_ref: &MutatorRef, description: String) acquires Collection {
         assert!(string::length(&description) <= MAX_DESCRIPTION_LENGTH, error::out_of_range(EDESCRIPTION_TOO_LONG));
         let collection = borrow_mut(mutator_ref);
+        if (std::features::module_event_migration_enabled()) {
+            event::emit(Mutation {
+                mutated_field_name: string::utf8(b"description"),
+                collection: object::address_to_object(mutator_ref.self),
+                old_value: collection.description,
+                new_value: description,
+            });
+        };
         collection.description = description;
         event::emit_event(
             &mut collection.mutation_events,
@@ -645,6 +709,14 @@ module aptos_token_objects::collection {
     public fun set_uri(mutator_ref: &MutatorRef, uri: String) acquires Collection {
         assert!(string::length(&uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG));
         let collection = borrow_mut(mutator_ref);
+        if (std::features::module_event_migration_enabled()) {
+            event::emit(Mutation {
+                mutated_field_name: string::utf8(b"uri"),
+                collection: object::address_to_object(mutator_ref.self),
+                old_value: collection.uri,
+                new_value: uri,
+            });
+        };
         collection.uri = uri;
         event::emit_event(
             &mut collection.mutation_events,
@@ -723,7 +795,10 @@ module aptos_token_objects::collection {
     }
 
     #[test(fx = @aptos_framework, creator = @0x123)]
-    fun test_create_mint_burn_for_concurrent(fx: &signer, creator: &signer) acquires FixedSupply, UnlimitedSupply, ConcurrentSupply {
+    fun test_create_mint_burn_for_concurrent(
+        fx: &signer,
+        creator: &signer
+    ) acquires FixedSupply, UnlimitedSupply, ConcurrentSupply {
         let feature = features::get_concurrent_token_v2_feature();
         features::change_feature_flags_for_testing(fx, vector[feature], vector[]);
 
@@ -785,7 +860,7 @@ module aptos_token_objects::collection {
         assert!(new_collection_name != name(collection), 0);
         set_name(&mutator_ref, new_collection_name);
         assert!(new_collection_name == name(collection), 1);
-        event::was_event_emitted(&Mutation {
+        event::was_event_emitted(&Mutation {
             mutated_field_name: string::utf8(b"name"),
             collection,
             old_value: collection_name,
diff --git a/aptos-move/framework/aptos-token-objects/sources/token.move b/aptos-move/framework/aptos-token-objects/sources/token.move
index 00b318ffe3f84..fca2a4e28900a 100644
--- a/aptos-move/framework/aptos-token-objects/sources/token.move
+++ b/aptos-move/framework/aptos-token-objects/sources/token.move
@@ -50,7 +50,8 @@ module aptos_token_objects::token {
         /// Will be populated until concurrent_token_v2_enabled feature flag is enabled.
         ///
         /// Unique identifier within the collection, optional, 0 means unassigned
-        index: u64, // DEPRECATED
+        index: u64,
+        // DEPRECATED
         /// A brief description of the token.
         description: String,
         /// Deprecated in favor of `name` inside TokenIdentifiers.
@@ -58,7 +59,8 @@ module aptos_token_objects::token {
         ///
         /// The name of the token, which should be unique within the collection; the length of name
         /// should be smaller than 128, characters, eg: "Aptos Animal #1234"
-        name: String,  // DEPRECATED
+        name: String,
+        // DEPRECATED
         /// The Uniform Resource Identifier (uri) pointing to the JSON file stored in off-chain
         /// storage; the URL length will likely need a maximum any suggestions?
         uri: String,
@@ -106,6 +108,14 @@ module aptos_token_objects::token {
         new_value: String
     }
 
+    #[event]
+    struct Mutation has drop, store {
+        token_address: address,
+        mutated_field_name: String,
+        old_value: String,
+        new_value: String
+    }
+
     inline fun create_common(
         constructor_ref: &ConstructorRef,
         creator_address: address,
@@ -120,7 +130,12 @@ module aptos_token_objects::token {
     ) {
         if (option::is_some(&name_with_index_suffix)) {
             // Be conservative, as we don't know what length the index will be, and assume worst case (20 chars in MAX_U64)
-            assert!(string::length(&name_prefix) + 20 + string::length(option::borrow(&name_with_index_suffix)) <= MAX_TOKEN_NAME_LENGTH, error::out_of_range(ETOKEN_NAME_TOO_LONG));
+            assert!(
+                string::length(&name_prefix) + 20 + string::length(
+                    option::borrow(&name_with_index_suffix)
+                ) <= MAX_TOKEN_NAME_LENGTH,
+                error::out_of_range(ETOKEN_NAME_TOO_LONG)
+            );
         } else {
             assert!(string::length(&name_prefix) <= MAX_TOKEN_NAME_LENGTH, error::out_of_range(ETOKEN_NAME_TOO_LONG));
         };
@@ -233,7 +248,16 @@ module aptos_token_objects::token {
     ): ConstructorRef {
         let creator_address = signer::address_of(creator);
         let constructor_ref = object::create_object(creator_address);
-        create_common(&constructor_ref, creator_address, collection_name, description, name, option::none(), royalty, uri);
+        create_common(
+            &constructor_ref,
+            creator_address,
+            collection_name,
+            description,
+            name,
+            option::none(),
+            royalty,
+            uri
+        );
         constructor_ref
     }
 
@@ -272,7 +296,16 @@ module aptos_token_objects::token {
     ): ConstructorRef {
         let creator_address = signer::address_of(creator);
         let constructor_ref = object::create_object(creator_address);
-        create_common(&constructor_ref, creator_address, collection_name, description, name_with_index_prefix, option::some(name_with_index_suffix), royalty, uri);
+        create_common(
+            &constructor_ref,
+            creator_address,
+            collection_name,
+            description,
+            name_with_index_prefix,
+            option::some(name_with_index_suffix),
+            royalty,
+            uri
+        );
         constructor_ref
     }
 
@@ -303,7 +336,16 @@ module aptos_token_objects::token {
         let seed = create_token_seed(&collection_name, &name);
 
         let constructor_ref = object::create_named_object(creator, seed);
-        create_common(&constructor_ref, creator_address, collection_name, description, name, option::none(), royalty, uri);
+        create_common(
+            &constructor_ref,
+            creator_address,
+            collection_name,
+            description,
+            name,
+            option::none(),
+            royalty,
+            uri
+        );
         constructor_ref
     }
 
@@ -341,7 +383,16 @@ module aptos_token_objects::token {
     ): ConstructorRef {
         let creator_address = signer::address_of(creator);
         let constructor_ref = object::create_object_from_account(creator);
-        create_common(&constructor_ref, creator_address, collection_name, description, name, option::none(), royalty, uri);
+        create_common(
+            &constructor_ref,
+            creator_address,
+            collection_name,
+            description,
+            name,
+            option::none(),
+            royalty,
+            uri
+        );
         constructor_ref
     }
 
@@ -554,6 +605,14 @@ module aptos_token_objects::token {
     public fun set_description(mutator_ref: &MutatorRef, description: String) acquires Token {
         assert!(string::length(&description) <= MAX_DESCRIPTION_LENGTH, error::out_of_range(EDESCRIPTION_TOO_LONG));
         let token = borrow_mut(mutator_ref);
+        if (std::features::module_event_migration_enabled()) {
+            event::emit(Mutation {
+                token_address: mutator_ref.self,
+                mutated_field_name: string::utf8(b"description"),
+                old_value: token.description,
+                new_value: description
+            })
+        };
         event::emit_event(
             &mut token.mutation_events,
             MutationEvent {
@@ -581,6 +640,14 @@ module aptos_token_objects::token {
             old_name
         };
 
+        if (std::features::module_event_migration_enabled()) {
+            event::emit(Mutation {
+                token_address: mutator_ref.self,
+                mutated_field_name: string::utf8(b"name"),
+                old_value: old_name,
+                new_value: name
+            })
+        };
         event::emit_event(
             &mut token.mutation_events,
             MutationEvent {
@@ -594,6 +661,14 @@ module aptos_token_objects::token {
     public fun set_uri(mutator_ref: &MutatorRef, uri: String) acquires Token {
         assert!(string::length(&uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG));
         let token = borrow_mut(mutator_ref);
+        if (std::features::module_event_migration_enabled()) {
+            event::emit(Mutation {
+                token_address: mutator_ref.self,
+                mutated_field_name: string::utf8(b"uri"),
+                old_value: token.uri,
+                new_value: uri,
+            })
+        };
         event::emit_event(
             &mut token.mutation_events,
             MutationEvent {
@@ -850,7 +925,7 @@ module aptos_token_objects::token {
         assert!(!object::is_object(token_addr), 2);
     }
 
-    #[test(creator = @0x123,fx = @std)]
+    #[test(creator = @0x123, fx = @std)]
     fun test_create_burn_and_delete(creator: &signer, fx: signer) acquires Token, TokenIdentifiers {
         use aptos_framework::account;
         use std::features;
@@ -905,7 +980,7 @@ module aptos_token_objects::token {
 
         let token_2_ref = create_numbered_token_helper(creator, collection, token_name);
         assert!(name(object::object_from_constructor_ref(&token_2_ref)) == std::string::utf8(b"token name2"), 1);
-        assert!(vector::length(&event::emitted_events()) == 1, 0);
+        assert!(vector::length(&event::emitted_events()) == 2, 0);
 
         let burn_ref = generate_burn_ref(&token_2_ref);
         let token_addr = object::address_from_constructor_ref(&token_2_ref);
diff --git a/aptos-move/framework/aptos-token/doc/token_event_store.md b/aptos-move/framework/aptos-token/doc/token_event_store.md
index 237c23cbd91c2..bc8bc9356b86d 100644
--- a/aptos-move/framework/aptos-token/doc/token_event_store.md
+++ b/aptos-move/framework/aptos-token/doc/token_event_store.md
@@ -7,14 +7,23 @@ This module provides utils to add and emit new token events that are not in toke
 
 
 -  [Struct `CollectionDescriptionMutateEvent`](#0x3_token_event_store_CollectionDescriptionMutateEvent)
+-  [Struct `CollectionDescriptionMutate`](#0x3_token_event_store_CollectionDescriptionMutate)
 -  [Struct `CollectionUriMutateEvent`](#0x3_token_event_store_CollectionUriMutateEvent)
+-  [Struct `CollectionUriMutate`](#0x3_token_event_store_CollectionUriMutate)
 -  [Struct `CollectionMaxiumMutateEvent`](#0x3_token_event_store_CollectionMaxiumMutateEvent)
+-  [Struct `CollectionMaxiumMutate`](#0x3_token_event_store_CollectionMaxiumMutate)
 -  [Struct `OptInTransferEvent`](#0x3_token_event_store_OptInTransferEvent)
+-  [Struct `OptInTransfer`](#0x3_token_event_store_OptInTransfer)
 -  [Struct `UriMutationEvent`](#0x3_token_event_store_UriMutationEvent)
+-  [Struct `UriMutation`](#0x3_token_event_store_UriMutation)
 -  [Struct `DefaultPropertyMutateEvent`](#0x3_token_event_store_DefaultPropertyMutateEvent)
+-  [Struct `DefaultPropertyMutate`](#0x3_token_event_store_DefaultPropertyMutate)
 -  [Struct `DescriptionMutateEvent`](#0x3_token_event_store_DescriptionMutateEvent)
+-  [Struct `DescriptionMutate`](#0x3_token_event_store_DescriptionMutate)
 -  [Struct `RoyaltyMutateEvent`](#0x3_token_event_store_RoyaltyMutateEvent)
+-  [Struct `RoyaltyMutate`](#0x3_token_event_store_RoyaltyMutate)
 -  [Struct `MaxiumMutateEvent`](#0x3_token_event_store_MaxiumMutateEvent)
+-  [Struct `MaximumMutate`](#0x3_token_event_store_MaximumMutate)
 -  [Resource `TokenEventStoreV1`](#0x3_token_event_store_TokenEventStoreV1)
 -  [Function `initialize_token_event_store`](#0x3_token_event_store_initialize_token_event_store)
 -  [Function `emit_collection_uri_mutate_event`](#0x3_token_event_store_emit_collection_uri_mutate_event)
@@ -42,6 +51,7 @@ This module provides utils to add and emit new token events that are not in toke
 
use 0x1::account;
 use 0x1::any;
 use 0x1::event;
+use 0x1::features;
 use 0x1::option;
 use 0x1::signer;
 use 0x1::string;
@@ -62,6 +72,53 @@ Event emitted when collection description is mutated
 
 
 
+
+Fields + + +
+
+creator_addr: address +
+
+ +
+
+collection_name: string::String +
+
+ +
+
+old_description: string::String +
+
+ +
+
+new_description: string::String +
+
+ +
+
+ + +
+ + + +## Struct `CollectionDescriptionMutate` + +Event emitted when collection description is mutated + + +
#[event]
+struct CollectionDescriptionMutate has drop, store
+
+ + +
Fields @@ -108,6 +165,53 @@ Event emitted when collection uri is mutated +
+Fields + + +
+
+creator_addr: address +
+
+ +
+
+collection_name: string::String +
+
+ +
+
+old_uri: string::String +
+
+ +
+
+new_uri: string::String +
+
+ +
+
+ + +
+ + + +## Struct `CollectionUriMutate` + +Event emitted when collection uri is mutated + + +
#[event]
+struct CollectionUriMutate has drop, store
+
+ + +
Fields @@ -154,6 +258,53 @@ Event emitted when the collection maximum is mutated +
+Fields + + +
+
+creator_addr: address +
+
+ +
+
+collection_name: string::String +
+
+ +
+
+old_maximum: u64 +
+
+ +
+
+new_maximum: u64 +
+
+ +
+
+ + +
+ + + +## Struct `CollectionMaxiumMutate` + +Event emitted when the collection maximum is mutated + + +
#[event]
+struct CollectionMaxiumMutate has drop, store
+
+ + +
Fields @@ -214,6 +365,41 @@ Event emitted when an user opt-in the direct transfer +
+ + + +## Struct `OptInTransfer` + +Event emitted when an user opt-in the direct transfer + + +
#[event]
+struct OptInTransfer has drop, store
+
+ + + +
+Fields + + +
+
+account_address: address +
+
+ +
+
+opt_in: bool +
+
+ True if the user opt in, false if the user opt-out +
+
+ +
@@ -228,6 +414,59 @@ Event emitted when the tokendata uri mutates +
+Fields + + +
+
+creator: address +
+
+ +
+
+collection: string::String +
+
+ +
+
+token: string::String +
+
+ +
+
+old_uri: string::String +
+
+ +
+
+new_uri: string::String +
+
+ +
+
+ + +
+ + + +## Struct `UriMutation` + +Event emitted when the tokendata uri mutates + + +
#[event]
+struct UriMutation has drop, store
+
+ + +
Fields @@ -280,6 +519,65 @@ Event emitted when mutating the default the token properties stored at tokendata +
+Fields + + +
+
+creator: address +
+
+ +
+
+collection: string::String +
+
+ +
+
+token: string::String +
+
+ +
+
+keys: vector<string::String> +
+
+ +
+
+old_values: vector<option::Option<property_map::PropertyValue>> +
+
+ we allow upsert so the old values might be none +
+
+new_values: vector<property_map::PropertyValue> +
+
+ +
+
+ + +
+ + + +## Struct `DefaultPropertyMutate` + +Event emitted when mutating the default the token properties stored at tokendata + + +
#[event]
+struct DefaultPropertyMutate has drop, store
+
+ + +
Fields @@ -338,6 +636,59 @@ Event emitted when the tokendata description is mutated +
+Fields + + +
+
+creator: address +
+
+ +
+
+collection: string::String +
+
+ +
+
+token: string::String +
+
+ +
+
+old_description: string::String +
+
+ +
+
+new_description: string::String +
+
+ +
+
+ + +
+ + + +## Struct `DescriptionMutate` + +Event emitted when the tokendata description is mutated + + +
#[event]
+struct DescriptionMutate has drop, store
+
+ + +
Fields @@ -390,6 +741,83 @@ Event emitted when the token royalty is mutated +
+Fields + + +
+
+creator: address +
+
+ +
+
+collection: string::String +
+
+ +
+
+token: string::String +
+
+ +
+
+old_royalty_numerator: u64 +
+
+ +
+
+old_royalty_denominator: u64 +
+
+ +
+
+old_royalty_payee_addr: address +
+
+ +
+
+new_royalty_numerator: u64 +
+
+ +
+
+new_royalty_denominator: u64 +
+
+ +
+
+new_royalty_payee_addr: address +
+
+ +
+
+ + +
+ + + +## Struct `RoyaltyMutate` + +Event emitted when the token royalty is mutated + + +
#[event]
+struct RoyaltyMutate has drop, store
+
+ + +
Fields @@ -466,6 +894,59 @@ Event emitted when the token maximum is mutated +
+Fields + + +
+
+creator: address +
+
+ +
+
+collection: string::String +
+
+ +
+
+token: string::String +
+
+ +
+
+old_maximum: u64 +
+
+ +
+
+new_maximum: u64 +
+
+ +
+
+ + +
+ + + +## Struct `MaximumMutate` + +Event emitted when the token maximum is mutated + + +
#[event]
+struct MaximumMutate has drop, store
+
+ + +
Fields @@ -649,6 +1130,16 @@ Emit the collection uri mutation event }; initialize_token_event_store(creator); let token_event_store = borrow_global_mut<TokenEventStoreV1>(signer::address_of(creator)); + if (std::features::module_event_migration_enabled()) { + event::emit( + CollectionUriMutate { + creator_addr: signer::address_of(creator), + collection_name: collection, + old_uri, + new_uri, + } + ); + }; event::emit_event<CollectionUriMutateEvent>( &mut token_event_store.collection_uri_mutate_events, event, @@ -685,6 +1176,16 @@ Emit the collection description mutation event }; initialize_token_event_store(creator); let token_event_store = borrow_global_mut<TokenEventStoreV1>(signer::address_of(creator)); + if (std::features::module_event_migration_enabled()) { + event::emit( + CollectionDescriptionMutate { + creator_addr: signer::address_of(creator), + collection_name: collection, + old_description, + new_description, + } + ); + }; event::emit_event<CollectionDescriptionMutateEvent>( &mut token_event_store.collection_description_mutate_events, event, @@ -721,6 +1222,16 @@ Emit the collection maximum mutation event }; initialize_token_event_store(creator); let token_event_store = borrow_global_mut<TokenEventStoreV1>(signer::address_of(creator)); + if (std::features::module_event_migration_enabled()) { + event::emit( + CollectionMaxiumMutate { + creator_addr: signer::address_of(creator), + collection_name: collection, + old_maximum, + new_maximum, + } + ); + }; event::emit_event<CollectionMaxiumMutateEvent>( &mut token_event_store.collection_maximum_mutate_events, event, @@ -754,6 +1265,13 @@ Emit the direct opt-in event }; initialize_token_event_store(account); let token_event_store = borrow_global_mut<TokenEventStoreV1>(signer::address_of(account)); + if (std::features::module_event_migration_enabled()) { + event::emit( + OptInTransfer { + account_address: signer::address_of(account), + opt_in, + }); + }; event::emit_event<OptInTransferEvent>( &mut token_event_store.opt_in_events, opt_in_event, @@ -800,6 +1318,16 @@ Emit URI mutation event initialize_token_event_store(creator); let token_event_store = borrow_global_mut<TokenEventStoreV1>(creator_addr); + if (std::features::module_event_migration_enabled()) { + event::emit( + UriMutation { + creator: creator_addr, + collection, + token, + old_uri, + new_uri, + }); + }; event::emit_event<UriMutationEvent>( &mut token_event_store.uri_mutate_events, event, @@ -848,6 +1376,17 @@ Emit tokendata property map mutation event initialize_token_event_store(creator); let token_event_store = borrow_global_mut<TokenEventStoreV1>(creator_addr); + if (std::features::module_event_migration_enabled()) { + event::emit( + DefaultPropertyMutate { + creator: creator_addr, + collection, + token, + keys, + old_values, + new_values, + }); + }; event::emit_event<DefaultPropertyMutateEvent>( &mut token_event_store.default_property_mutate_events, event, @@ -894,6 +1433,16 @@ Emit description mutation event initialize_token_event_store(creator); let token_event_store = borrow_global_mut<TokenEventStoreV1>(creator_addr); + if (std::features::module_event_migration_enabled()) { + event::emit( + DescriptionMutate { + creator: creator_addr, + collection, + token, + old_description, + new_description, + }); + }; event::emit_event<DescriptionMutateEvent>( &mut token_event_store.description_mutate_events, event, @@ -947,6 +1496,20 @@ Emit royalty mutation event initialize_token_event_store(creator); let token_event_store = borrow_global_mut<TokenEventStoreV1>(creator_addr); + if (std::features::module_event_migration_enabled()) { + event::emit( + RoyaltyMutate { + creator: creator_addr, + collection, + token, + old_royalty_numerator, + old_royalty_denominator, + old_royalty_payee_addr, + new_royalty_numerator, + new_royalty_denominator, + new_royalty_payee_addr, + }); + }; event::emit_event<RoyaltyMutateEvent>( &mut token_event_store.royalty_mutate_events, event, @@ -993,6 +1556,16 @@ Emit maximum mutation event initialize_token_event_store(creator); let token_event_store = borrow_global_mut<TokenEventStoreV1>(creator_addr); + if (std::features::module_event_migration_enabled()) { + event::emit( + MaximumMutate { + creator: creator_addr, + collection, + token, + old_maximum, + new_maximum, + }); + }; event::emit_event<MaxiumMutateEvent>( &mut token_event_store.maximum_mutate_events, event, diff --git a/aptos-move/framework/aptos-token/doc/token_transfers.md b/aptos-move/framework/aptos-token/doc/token_transfers.md index be5cce8f609e1..a01d9c238daba 100644 --- a/aptos-move/framework/aptos-token/doc/token_transfers.md +++ b/aptos-move/framework/aptos-token/doc/token_transfers.md @@ -93,7 +93,8 @@ This module provides the foundation for transferring of Tokens -
struct TokenOfferId has copy, drop, store
+
#[event]
+struct TokenOfferId has copy, drop, store
 
@@ -126,7 +127,8 @@ This module provides the foundation for transferring of Tokens -
struct TokenOfferEvent has drop, store
+
#[event]
+struct TokenOfferEvent has drop, store
 
@@ -165,7 +167,8 @@ This module provides the foundation for transferring of Tokens -
struct TokenCancelOfferEvent has drop, store
+
#[event]
+struct TokenCancelOfferEvent has drop, store
 
@@ -204,7 +207,8 @@ This module provides the foundation for transferring of Tokens -
struct TokenClaimEvent has drop, store
+
#[event]
+struct TokenClaimEvent has drop, store
 
diff --git a/aptos-move/framework/aptos-token/sources/token_event_store.move b/aptos-move/framework/aptos-token/sources/token_event_store.move index 52ba6c7c69ce0..0171e9cb9f88f 100644 --- a/aptos-move/framework/aptos-token/sources/token_event_store.move +++ b/aptos-move/framework/aptos-token/sources/token_event_store.move @@ -23,6 +23,15 @@ module aptos_token::token_event_store { new_description: String, } + #[event] + /// Event emitted when collection description is mutated + struct CollectionDescriptionMutate has drop, store { + creator_addr: address, + collection_name: String, + old_description: String, + new_description: String, + } + /// Event emitted when collection uri is mutated struct CollectionUriMutateEvent has drop, store { creator_addr: address, @@ -31,6 +40,15 @@ module aptos_token::token_event_store { new_uri: String, } + #[event] + /// Event emitted when collection uri is mutated + struct CollectionUriMutate has drop, store { + creator_addr: address, + collection_name: String, + old_uri: String, + new_uri: String, + } + /// Event emitted when the collection maximum is mutated struct CollectionMaxiumMutateEvent has drop, store { creator_addr: address, @@ -39,6 +57,15 @@ module aptos_token::token_event_store { new_maximum: u64, } + #[event] + /// Event emitted when the collection maximum is mutated + struct CollectionMaxiumMutate has drop, store { + creator_addr: address, + collection_name: String, + old_maximum: u64, + new_maximum: u64, + } + // // Token transfer related events // @@ -49,6 +76,14 @@ module aptos_token::token_event_store { opt_in: bool } + #[event] + /// Event emitted when an user opt-in the direct transfer + struct OptInTransfer has drop, store { + account_address: address, + /// True if the user opt in, false if the user opt-out + opt_in: bool + } + // // Token mutation events // @@ -62,6 +97,16 @@ module aptos_token::token_event_store { new_uri: String, } + #[event] + /// Event emitted when the tokendata uri mutates + struct UriMutation has drop, store { + creator: address, + collection: String, + token: String, + old_uri: String, + new_uri: String, + } + /// Event emitted when mutating the default the token properties stored at tokendata struct DefaultPropertyMutateEvent has drop, store { creator: address, @@ -73,6 +118,18 @@ module aptos_token::token_event_store { new_values: vector, } + #[event] + /// Event emitted when mutating the default the token properties stored at tokendata + struct DefaultPropertyMutate has drop, store { + creator: address, + collection: String, + token: String, + keys: vector, + /// we allow upsert so the old values might be none + old_values: vector>, + new_values: vector, + } + /// Event emitted when the tokendata description is mutated struct DescriptionMutateEvent has drop, store { creator: address, @@ -82,6 +139,16 @@ module aptos_token::token_event_store { new_description: String, } + #[event] + /// Event emitted when the tokendata description is mutated + struct DescriptionMutate has drop, store { + creator: address, + collection: String, + token: String, + old_description: String, + new_description: String, + } + /// Event emitted when the token royalty is mutated struct RoyaltyMutateEvent has drop, store { creator: address, @@ -95,6 +162,20 @@ module aptos_token::token_event_store { new_royalty_payee_addr: address, } + #[event] + /// Event emitted when the token royalty is mutated + struct RoyaltyMutate has drop, store { + creator: address, + collection: String, + token: String, + old_royalty_numerator: u64, + old_royalty_denominator: u64, + old_royalty_payee_addr: address, + new_royalty_numerator: u64, + new_royalty_denominator: u64, + new_royalty_payee_addr: address, + } + /// Event emitted when the token maximum is mutated struct MaxiumMutateEvent has drop, store { creator: address, @@ -104,6 +185,16 @@ module aptos_token::token_event_store { new_maximum: u64, } + #[event] + /// Event emitted when the token maximum is mutated + struct MaximumMutate has drop, store { + creator: address, + collection: String, + token: String, + old_maximum: u64, + new_maximum: u64, + } + struct TokenEventStoreV1 has key { /// collection mutation events collection_uri_mutate_events: EventHandle, @@ -148,6 +239,16 @@ module aptos_token::token_event_store { }; initialize_token_event_store(creator); let token_event_store = borrow_global_mut(signer::address_of(creator)); + if (std::features::module_event_migration_enabled()) { + event::emit( + CollectionUriMutate { + creator_addr: signer::address_of(creator), + collection_name: collection, + old_uri, + new_uri, + } + ); + }; event::emit_event( &mut token_event_store.collection_uri_mutate_events, event, @@ -164,6 +265,16 @@ module aptos_token::token_event_store { }; initialize_token_event_store(creator); let token_event_store = borrow_global_mut(signer::address_of(creator)); + if (std::features::module_event_migration_enabled()) { + event::emit( + CollectionDescriptionMutate { + creator_addr: signer::address_of(creator), + collection_name: collection, + old_description, + new_description, + } + ); + }; event::emit_event( &mut token_event_store.collection_description_mutate_events, event, @@ -180,6 +291,16 @@ module aptos_token::token_event_store { }; initialize_token_event_store(creator); let token_event_store = borrow_global_mut(signer::address_of(creator)); + if (std::features::module_event_migration_enabled()) { + event::emit( + CollectionMaxiumMutate { + creator_addr: signer::address_of(creator), + collection_name: collection, + old_maximum, + new_maximum, + } + ); + }; event::emit_event( &mut token_event_store.collection_maximum_mutate_events, event, @@ -193,6 +314,13 @@ module aptos_token::token_event_store { }; initialize_token_event_store(account); let token_event_store = borrow_global_mut(signer::address_of(account)); + if (std::features::module_event_migration_enabled()) { + event::emit( + OptInTransfer { + account_address: signer::address_of(account), + opt_in, + }); + }; event::emit_event( &mut token_event_store.opt_in_events, opt_in_event, @@ -219,6 +347,16 @@ module aptos_token::token_event_store { initialize_token_event_store(creator); let token_event_store = borrow_global_mut(creator_addr); + if (std::features::module_event_migration_enabled()) { + event::emit( + UriMutation { + creator: creator_addr, + collection, + token, + old_uri, + new_uri, + }); + }; event::emit_event( &mut token_event_store.uri_mutate_events, event, @@ -247,6 +385,17 @@ module aptos_token::token_event_store { initialize_token_event_store(creator); let token_event_store = borrow_global_mut(creator_addr); + if (std::features::module_event_migration_enabled()) { + event::emit( + DefaultPropertyMutate { + creator: creator_addr, + collection, + token, + keys, + old_values, + new_values, + }); + }; event::emit_event( &mut token_event_store.default_property_mutate_events, event, @@ -273,6 +422,16 @@ module aptos_token::token_event_store { initialize_token_event_store(creator); let token_event_store = borrow_global_mut(creator_addr); + if (std::features::module_event_migration_enabled()) { + event::emit( + DescriptionMutate { + creator: creator_addr, + collection, + token, + old_description, + new_description, + }); + }; event::emit_event( &mut token_event_store.description_mutate_events, event, @@ -306,6 +465,20 @@ module aptos_token::token_event_store { initialize_token_event_store(creator); let token_event_store = borrow_global_mut(creator_addr); + if (std::features::module_event_migration_enabled()) { + event::emit( + RoyaltyMutate { + creator: creator_addr, + collection, + token, + old_royalty_numerator, + old_royalty_denominator, + old_royalty_payee_addr, + new_royalty_numerator, + new_royalty_denominator, + new_royalty_payee_addr, + }); + }; event::emit_event( &mut token_event_store.royalty_mutate_events, event, @@ -332,6 +505,16 @@ module aptos_token::token_event_store { initialize_token_event_store(creator); let token_event_store = borrow_global_mut(creator_addr); + if (std::features::module_event_migration_enabled()) { + event::emit( + MaximumMutate { + creator: creator_addr, + collection, + token, + old_maximum, + new_maximum, + }); + }; event::emit_event( &mut token_event_store.maximum_mutate_events, event, diff --git a/aptos-move/framework/aptos-token/sources/token_transfers.move b/aptos-move/framework/aptos-token/sources/token_transfers.move index 796a7b79abb21..5b58becb605c9 100644 --- a/aptos-move/framework/aptos-token/sources/token_transfers.move +++ b/aptos-move/framework/aptos-token/sources/token_transfers.move @@ -22,23 +22,27 @@ module aptos_token::token_transfers { claim_events: EventHandle, } + #[event] struct TokenOfferId has copy, drop, store { to_addr: address, token_id: TokenId, } + #[event] struct TokenOfferEvent has drop, store { to_address: address, token_id: TokenId, amount: u64, } + #[event] struct TokenCancelOfferEvent has drop, store { to_address: address, token_id: TokenId, amount: u64, } + #[event] struct TokenClaimEvent has drop, store { to_address: address, token_id: TokenId, diff --git a/aptos-move/framework/move-stdlib/doc/features.md b/aptos-move/framework/move-stdlib/doc/features.md index 1f0eb063083bd..4c90588f5bc33 100644 --- a/aptos-move/framework/move-stdlib/doc/features.md +++ b/aptos-move/framework/move-stdlib/doc/features.md @@ -106,6 +106,8 @@ return true. - [Function `multisig_v2_enhancement_feature_enabled`](#0x1_features_multisig_v2_enhancement_feature_enabled) - [Function `get_delegation_pool_allowlisting_feature`](#0x1_features_get_delegation_pool_allowlisting_feature) - [Function `delegation_pool_allowlisting_enabled`](#0x1_features_delegation_pool_allowlisting_enabled) +- [Function `get_module_event_migration_feature`](#0x1_features_get_module_event_migration_feature) +- [Function `module_event_migration_enabled`](#0x1_features_module_event_migration_enabled) - [Function `change_feature_flags`](#0x1_features_change_feature_flags) - [Function `change_feature_flags_internal`](#0x1_features_change_feature_flags_internal) - [Function `change_feature_flags_for_next_epoch`](#0x1_features_change_feature_flags_for_next_epoch) @@ -545,6 +547,18 @@ Lifetime: transient + + +Whether aptos_framwork enables the behavior of module event migration. + +Lifetime: transient + + +
const MODULE_EVENT_MIGRATION: u64 = 57;
+
+ + + Whether multisig accounts (different from accounts with multi-ed25519 auth keys) are enabled. @@ -2482,6 +2496,52 @@ Lifetime: transient +
+ + + +## Function `get_module_event_migration_feature` + + + +
public fun get_module_event_migration_feature(): u64
+
+ + + +
+Implementation + + +
public fun get_module_event_migration_feature(): u64 { MODULE_EVENT_MIGRATION }
+
+ + + +
+ + + +## Function `module_event_migration_enabled` + + + +
public fun module_event_migration_enabled(): bool
+
+ + + +
+Implementation + + +
public fun module_event_migration_enabled(): bool acquires Features {
+    is_enabled(MODULE_EVENT_MIGRATION)
+}
+
+ + +
diff --git a/aptos-move/framework/move-stdlib/sources/configs/features.move b/aptos-move/framework/move-stdlib/sources/configs/features.move index 8f4e511b915cc..a0b802dd7256a 100644 --- a/aptos-move/framework/move-stdlib/sources/configs/features.move +++ b/aptos-move/framework/move-stdlib/sources/configs/features.move @@ -55,7 +55,9 @@ module std::features { /// This is needed because of the introduction of new native functions. /// Lifetime: transient const SHA_512_AND_RIPEMD_160_NATIVES: u64 = 3; + public fun get_sha_512_and_ripemd_160_feature(): u64 { SHA_512_AND_RIPEMD_160_NATIVES } + public fun sha_512_and_ripemd_160_enabled(): bool acquires Features { is_enabled(SHA_512_AND_RIPEMD_160_NATIVES) } @@ -64,7 +66,9 @@ module std::features { /// This is needed because of the introduction of a new native function. /// Lifetime: transient const APTOS_STD_CHAIN_ID_NATIVES: u64 = 4; + public fun get_aptos_stdlib_chain_id_feature(): u64 { APTOS_STD_CHAIN_ID_NATIVES } + public fun aptos_stdlib_chain_id_enabled(): bool acquires Features { is_enabled(APTOS_STD_CHAIN_ID_NATIVES) } @@ -72,7 +76,9 @@ module std::features { /// Whether to allow the use of binary format version v6. /// Lifetime: transient const VM_BINARY_FORMAT_V6: u64 = 5; + public fun get_vm_binary_format_v6(): u64 { VM_BINARY_FORMAT_V6 } + public fun allow_vm_binary_format_v6(): bool acquires Features { is_enabled(VM_BINARY_FORMAT_V6) } @@ -80,7 +86,9 @@ module std::features { /// Whether gas fees are collected and distributed to the block proposers. /// Lifetime: transient const COLLECT_AND_DISTRIBUTE_GAS_FEES: u64 = 6; + public fun get_collect_and_distribute_gas_fees_feature(): u64 { COLLECT_AND_DISTRIBUTE_GAS_FEES } + public fun collect_and_distribute_gas_fees(): bool acquires Features { is_enabled(COLLECT_AND_DISTRIBUTE_GAS_FEES) } @@ -89,7 +97,9 @@ module std::features { /// This is needed because of the introduction of a new native function. /// Lifetime: transient const MULTI_ED25519_PK_VALIDATE_V2_NATIVES: u64 = 7; + public fun multi_ed25519_pk_validate_v2_feature(): u64 { MULTI_ED25519_PK_VALIDATE_V2_NATIVES } + public fun multi_ed25519_pk_validate_v2_enabled(): bool acquires Features { is_enabled(MULTI_ED25519_PK_VALIDATE_V2_NATIVES) } @@ -98,7 +108,9 @@ module std::features { /// This is needed because of the introduction of new native function(s). /// Lifetime: transient const BLAKE2B_256_NATIVE: u64 = 8; + public fun get_blake2b_256_feature(): u64 { BLAKE2B_256_NATIVE } + public fun blake2b_256_enabled(): bool acquires Features { is_enabled(BLAKE2B_256_NATIVE) } @@ -106,14 +118,18 @@ module std::features { /// Whether resource groups are enabled. /// This is needed because of new attributes for structs and a change in storage representation. const RESOURCE_GROUPS: u64 = 9; + public fun get_resource_groups_feature(): u64 { RESOURCE_GROUPS } + public fun resource_groups_enabled(): bool acquires Features { is_enabled(RESOURCE_GROUPS) } /// Whether multisig accounts (different from accounts with multi-ed25519 auth keys) are enabled. const MULTISIG_ACCOUNTS: u64 = 10; + public fun get_multisig_accounts_feature(): u64 { MULTISIG_ACCOUNTS } + public fun multisig_accounts_enabled(): bool acquires Features { is_enabled(MULTISIG_ACCOUNTS) } @@ -121,7 +137,9 @@ module std::features { /// Whether delegation pools are enabled. /// Lifetime: transient const DELEGATION_POOLS: u64 = 11; + public fun get_delegation_pools_feature(): u64 { DELEGATION_POOLS } + public fun delegation_pools_enabled(): bool acquires Features { is_enabled(DELEGATION_POOLS) } @@ -214,6 +232,7 @@ module std::features { /// available. This is needed because of the introduction of a new native function. /// Lifetime: transient const BULLETPROOFS_NATIVES: u64 = 24; + public fun get_bulletproofs_feature(): u64 { BULLETPROOFS_NATIVES } public fun bulletproofs_enabled(): bool acquires Features { @@ -446,6 +465,17 @@ module std::features { is_enabled(DELEGATION_POOL_ALLOWLISTING) } + /// Whether aptos_framwork enables the behavior of module event migration. + /// + /// Lifetime: transient + const MODULE_EVENT_MIGRATION: u64 = 57; + + public fun get_module_event_migration_feature(): u64 { MODULE_EVENT_MIGRATION } + + public fun module_event_migration_enabled(): bool acquires Features { + is_enabled(MODULE_EVENT_MIGRATION) + } + // ============================================================================================ // Feature Flag Implementation diff --git a/aptos-move/move-examples/veiled_coin/sources/veiled_coin.move b/aptos-move/move-examples/veiled_coin/sources/veiled_coin.move index 9f79636486e36..bbf7bbda3834a 100644 --- a/aptos-move/move-examples/veiled_coin/sources/veiled_coin.move +++ b/aptos-move/move-examples/veiled_coin/sources/veiled_coin.move @@ -639,7 +639,7 @@ module veiled_coin::veiled_coin { sender_veiled_coin_store.veiled_balance = elgamal::compress_ciphertext(&veiled_balance); // Once everything succeeds, emit an event to indicate a veiled withdrawal occurred - event::emit( + event::emit( Withdraw { user: sender_addr }, ); diff --git a/types/src/on_chain_config/aptos_features.rs b/types/src/on_chain_config/aptos_features.rs index e31a0ab736c0f..b44afc2c21e56 100644 --- a/types/src/on_chain_config/aptos_features.rs +++ b/types/src/on_chain_config/aptos_features.rs @@ -68,6 +68,7 @@ pub enum FeatureFlag { KEYLESS_ACCOUNTS_WITH_PASSKEYS = 54, MULTISIG_V2_ENHANCEMENT = 55, DELEGATION_POOL_ALLOWLISTING = 56, + MODULE_EVENT_MIGRATION = 57, } impl FeatureFlag { @@ -122,6 +123,7 @@ impl FeatureFlag { FeatureFlag::KEYLESS_ACCOUNTS_WITH_PASSKEYS, FeatureFlag::MULTISIG_V2_ENHANCEMENT, FeatureFlag::DELEGATION_POOL_ALLOWLISTING, + FeatureFlag::MODULE_EVENT_MIGRATION, ] } } From e292612324aa5a71d398d7c12748a78b6e50dcf1 Mon Sep 17 00:00:00 2001 From: Josh Lind Date: Fri, 5 Apr 2024 19:15:31 -0400 Subject: [PATCH 22/36] [Config] Add Config Optimizer for ExecutionConfig. --- aptos-node/src/utils.rs | 7 +- config/src/config/config_optimizer.rs | 16 +- config/src/config/execution_config.rs | 213 +++++++++++++++++++++++++- 3 files changed, 223 insertions(+), 13 deletions(-) diff --git a/aptos-node/src/utils.rs b/aptos-node/src/utils.rs index 285e335aab1df..de630b46fdd79 100644 --- a/aptos-node/src/utils.rs +++ b/aptos-node/src/utils.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use anyhow::anyhow; -use aptos_config::config::{NodeConfig, DEFAULT_CONCURRENCY_LEVEL}; +use aptos_config::config::{NodeConfig, DEFAULT_EXECUTION_CONCURRENCY_LEVEL}; use aptos_storage_interface::{state_view::LatestDbStateCheckpointView, DbReaderWriter}; use aptos_types::{ account_config::CORE_CODE_ADDRESS, account_view::AccountView, chain_id::ChainId, @@ -51,7 +51,10 @@ pub fn fetch_chain_id(db: &DbReaderWriter) -> anyhow::Result { pub fn set_aptos_vm_configurations(node_config: &NodeConfig) { AptosVM::set_paranoid_type_checks(node_config.execution.paranoid_type_verification); let effective_concurrency_level = if node_config.execution.concurrency_level == 0 { - min(DEFAULT_CONCURRENCY_LEVEL, (num_cpus::get() / 2) as u16) + min( + DEFAULT_EXECUTION_CONCURRENCY_LEVEL, + (num_cpus::get() / 2) as u16, + ) } else { node_config.execution.concurrency_level }; diff --git a/config/src/config/config_optimizer.rs b/config/src/config/config_optimizer.rs index 0e9476fbc08b0..8947a4c7644c6 100644 --- a/config/src/config/config_optimizer.rs +++ b/config/src/config/config_optimizer.rs @@ -5,8 +5,8 @@ use super::{Identity, IdentityFromConfig, IdentitySource, IndexerGrpcConfig}; use crate::{ config::{ node_config_loader::NodeType, utils::get_config_name, AdminServiceConfig, Error, - IndexerConfig, InspectionServiceConfig, LoggerConfig, MempoolConfig, NodeConfig, Peer, - PeerRole, PeerSet, StateSyncConfig, + ExecutionConfig, IndexerConfig, InspectionServiceConfig, LoggerConfig, MempoolConfig, + NodeConfig, Peer, PeerRole, PeerSet, StateSyncConfig, }, network_id::NetworkId, }; @@ -105,6 +105,9 @@ impl ConfigOptimizer for NodeConfig { // Optimize only the relevant sub-configs let mut optimizers_with_modifications = vec![]; + if ExecutionConfig::optimize(node_config, local_config_yaml, node_type, chain_id)? { + optimizers_with_modifications.push(ExecutionConfig::get_optimizer_name()); + } if IndexerConfig::optimize(node_config, local_config_yaml, node_type, chain_id)? { optimizers_with_modifications.push(IndexerConfig::get_optimizer_name()); } @@ -308,11 +311,13 @@ fn build_seed_peer( mod tests { use super::*; use crate::{ - config::{node_startup_config::NodeStartupConfig, NetworkConfig, StorageConfig}, + config::{ + node_startup_config::NodeStartupConfig, NetworkConfig, StorageConfig, WaypointConfig, + }, network_id::NetworkId, }; use aptos_crypto::{Uniform, ValidCryptoMaterial}; - use aptos_types::account_address::AccountAddress; + use aptos_types::{account_address::AccountAddress, waypoint::Waypoint}; use rand::rngs::OsRng; use std::{io::Write, path::PathBuf}; use tempfile::{tempdir, NamedTempFile}; @@ -329,6 +334,9 @@ mod tests { // Create a default node config (with optimization enabled) let mut node_config = NodeConfig::default(); + // Set the base waypoint config + node_config.base.waypoint = WaypointConfig::FromConfig(Waypoint::default()); + // Optimize the node config for mainnet VFNs and verify modifications are made let modified_config = NodeConfig::optimize( &mut node_config, diff --git a/config/src/config/execution_config.rs b/config/src/config/execution_config.rs index f6c0482538564..0959ba8aa9d6d 100644 --- a/config/src/config/execution_config.rs +++ b/config/src/config/execution_config.rs @@ -4,19 +4,30 @@ use super::WaypointConfig; use crate::config::{ - config_sanitizer::ConfigSanitizer, node_config_loader::NodeType, - transaction_filter_type::Filter, utils::RootPath, Error, NodeConfig, + config_optimizer::ConfigOptimizer, config_sanitizer::ConfigSanitizer, + node_config_loader::NodeType, transaction_filter_type::Filter, utils::RootPath, Error, + NodeConfig, }; -use aptos_types::{chain_id::ChainId, transaction::Transaction}; +use aptos_types::{chain_id::ChainId, transaction::Transaction, waypoint::Waypoint}; use serde::{Deserialize, Serialize}; +use serde_yaml::Value; use std::{ fs::File, io::{Read, Write}, path::PathBuf, + str::FromStr, }; -const GENESIS_DEFAULT: &str = "genesis.blob"; -pub const DEFAULT_CONCURRENCY_LEVEL: u16 = 32; +// Default execution concurrency level +pub const DEFAULT_EXECUTION_CONCURRENCY_LEVEL: u16 = 32; + +// Genesis constants +const GENESIS_BLOB_FILENAME: &str = "genesis.blob"; +const GENESIS_VERSION: u64 = 0; +const MAINNET_GENESIS_WAYPOINT: &str = + "0:6072b68a942aace147e0655c5704beaa255c84a7829baa4e72a500f1516584c4"; +const TESTNET_GENESIS_WAYPOINT: &str = + "0:4b56f15c1dcef7f9f3eb4b4798c0cba0f1caacc0d35f1c80ad9b7a21f1f8b454"; #[derive(Clone, Deserialize, PartialEq, Eq, Serialize)] #[serde(default, deny_unknown_fields)] @@ -125,7 +136,7 @@ impl ExecutionConfig { pub fn save_to_path(&mut self, root_dir: &RootPath) -> Result<(), Error> { if let Some(genesis) = &self.genesis { if self.genesis_file_location.as_os_str().is_empty() { - self.genesis_file_location = PathBuf::from(GENESIS_DEFAULT); + self.genesis_file_location = PathBuf::from(GENESIS_BLOB_FILENAME); } let path = root_dir.full_path(&self.genesis_file_location); let mut file = File::create(path).map_err(|e| Error::IO("genesis".into(), e))?; @@ -169,6 +180,57 @@ impl ConfigSanitizer for ExecutionConfig { } } +impl ConfigOptimizer for ExecutionConfig { + fn optimize( + node_config: &mut NodeConfig, + local_config_yaml: &Value, + _node_type: NodeType, + chain_id: Option, + ) -> Result { + let execution_config = &mut node_config.execution; + let local_execution_config_yaml = &local_config_yaml["execution"]; + + // If the base config has a non-genesis waypoint, we should automatically + // inject the genesis waypoint into the execution config (if it doesn't exist). + // We do this for testnet and mainnet only (as they are long lived networks). + if node_config.base.waypoint.waypoint().version() != GENESIS_VERSION + && execution_config.genesis_waypoint.is_none() + && local_execution_config_yaml["genesis_waypoint"].is_null() + { + // Determine the genesis waypoint string to use + let genesis_waypoint_str = match chain_id { + Some(chain_id) => { + if chain_id.is_mainnet() { + MAINNET_GENESIS_WAYPOINT + } else if chain_id.is_testnet() { + TESTNET_GENESIS_WAYPOINT + } else { + return Ok(false); // Return early (this is not testnet or mainnet) + } + }, + None => return Ok(false), // Return early (no chain ID was specified!) + }; + + // Construct a genesis waypoint from the string + let genesis_waypoint = match Waypoint::from_str(genesis_waypoint_str) { + Ok(waypoint) => waypoint, + Err(error) => panic!( + "Invalid genesis waypoint string: {:?}. Error: {:?}", + genesis_waypoint_str, error + ), + }; + let genesis_waypoint_config = WaypointConfig::FromConfig(genesis_waypoint); + + // Inject the genesis waypoint into the execution config + execution_config.genesis_waypoint = Some(genesis_waypoint_config); + + return Ok(true); // The config was modified + } + + Ok(false) // The config was not modified + } +} + #[cfg(test)] mod test { use super::*; @@ -177,6 +239,140 @@ mod test { transaction::{ChangeSet, Transaction, WriteSetPayload}, write_set::WriteSetMut, }; + use std::{assert_eq, matches, vec}; + + // Useful test constants + const GENESIS_WAYPOINT: &str = + "0:00000000002aace147e0655c5704beaa255c84a7829baa4e72a5000000000000"; + const NON_GENESIS_WAYPOINT: &str = + "100:aaaaaaaaaa2aace147e0655c5704beaa255c84a7829baa4e72a500aaaaaaaaaa"; + + #[test] + fn test_optimize_execution_config_genesis() { + // Create a default node config + let mut node_config = NodeConfig::default(); + + // Verify the execution config does not have a genesis waypoint + assert!(&node_config.execution.genesis_waypoint.is_none()); + + // Inject a genesis waypoint into the base config + let genesis_waypoint = Waypoint::from_str(GENESIS_WAYPOINT).unwrap(); + node_config.base.waypoint = WaypointConfig::FromConfig(genesis_waypoint); + + // Optimize the config and verify that no modifications are made + let modified_config = ExecutionConfig::optimize( + &mut node_config, + &serde_yaml::from_str("{}").unwrap(), // An empty local config, + NodeType::Validator, + Some(ChainId::testnet()), + ) + .unwrap(); + assert!(!modified_config); + } + + #[test] + fn test_optimize_execution_config_non_genesis_mainnet() { + // Create a default node config + let mut node_config = NodeConfig::default(); + + // Verify the execution config does not have a genesis waypoint + assert!(&node_config.execution.genesis_waypoint.is_none()); + + // Inject a non-genesis waypoint into the base config + let non_genesis_waypoint = Waypoint::from_str(NON_GENESIS_WAYPOINT).unwrap(); + node_config.base.waypoint = WaypointConfig::FromConfig(non_genesis_waypoint); + + // Optimize the config for mainnet and verify modifications are made + let modified_config = ExecutionConfig::optimize( + &mut node_config, + &serde_yaml::from_str("{}").unwrap(), // An empty local config, + NodeType::Validator, + Some(ChainId::mainnet()), + ) + .unwrap(); + assert!(modified_config); + + // Verify that the mainnet genesis waypoint was injected into the execution config + let expected_genesis_waypoint = + WaypointConfig::FromConfig(Waypoint::from_str(MAINNET_GENESIS_WAYPOINT).unwrap()); + assert_eq!( + &node_config.execution.genesis_waypoint, + &Some(expected_genesis_waypoint) + ); + } + + #[test] + fn test_optimize_execution_config_non_genesis_testnet() { + // Create a default node config + let mut node_config = NodeConfig::default(); + + // Verify the execution config does not have a genesis waypoint + assert!(&node_config.execution.genesis_waypoint.is_none()); + + // Inject a non-genesis waypoint into the base config + let non_genesis_waypoint = Waypoint::from_str(NON_GENESIS_WAYPOINT).unwrap(); + node_config.base.waypoint = WaypointConfig::FromConfig(non_genesis_waypoint); + + // Optimize the config for testnet and verify modifications are made + let modified_config = ExecutionConfig::optimize( + &mut node_config, + &serde_yaml::from_str("{}").unwrap(), // An empty local config, + NodeType::PublicFullnode, + Some(ChainId::testnet()), + ) + .unwrap(); + assert!(modified_config); + + // Verify that the testnet genesis waypoint was injected into the execution config + let expected_genesis_waypoint = + WaypointConfig::FromConfig(Waypoint::from_str(TESTNET_GENESIS_WAYPOINT).unwrap()); + assert_eq!( + &node_config.execution.genesis_waypoint, + &Some(expected_genesis_waypoint) + ); + } + + #[test] + fn test_optimize_execution_config_skipped() { + // Create a default node config + let mut node_config = NodeConfig::default(); + + // Verify the execution config does not have a genesis waypoint + assert!(&node_config.execution.genesis_waypoint.is_none()); + + // Inject a non-genesis waypoint into the base config + let non_genesis_waypoint = Waypoint::from_str(NON_GENESIS_WAYPOINT).unwrap(); + node_config.base.waypoint = WaypointConfig::FromConfig(non_genesis_waypoint); + + // Optimize the config for a local network and verify that no modifications are made + let modified_config = ExecutionConfig::optimize( + &mut node_config, + &serde_yaml::from_str("{}").unwrap(), // An empty local config, + NodeType::Validator, + Some(ChainId::new(100)), // Neither testnet or mainnet + ) + .unwrap(); + assert!(!modified_config); + + // Create a local config YAML with an execution config explicitly setting the genesis waypoint + let local_config_yaml = serde_yaml::from_str( + r#" + execution: + genesis_waypoint: "0:aaaaaaaa" + "#, + ) + .unwrap(); + + // Optimize the config for mainnet and verify that no modifications are made + let modified_config = ExecutionConfig::optimize( + &mut node_config, + &local_config_yaml, // The local config with an explicit genesis waypoint + NodeType::Validator, + Some(ChainId::mainnet()), + ) + .unwrap(); + assert!(!modified_config); + } #[test] fn test_sanitize_valid_execution_config() { @@ -253,7 +449,10 @@ mod test { let root_dir = RootPath::new_path(path.path()); config.save_to_path(&root_dir).expect("Unable to save"); // Verifies some without path - assert_eq!(config.genesis_file_location, PathBuf::from(GENESIS_DEFAULT)); + assert_eq!( + config.genesis_file_location, + PathBuf::from(GENESIS_BLOB_FILENAME) + ); config.genesis = None; let result = config.load_from_path(&root_dir); From df715afc2ca6646bcdee63e44e30c549ebe14bf3 Mon Sep 17 00:00:00 2001 From: Josh Lind Date: Fri, 5 Apr 2024 19:15:41 -0400 Subject: [PATCH 23/36] [State Sync] Add unit tests for waypoint verification. --- .../state-sync-driver/src/bootstrapper.rs | 29 ++- .../src/tests/bootstrapper.rs | 166 ++++++++++++++++++ .../state-sync-driver/src/tests/utils.rs | 6 +- types/src/epoch_state.rs | 4 + 4 files changed, 194 insertions(+), 11 deletions(-) diff --git a/state-sync/state-sync-driver/src/bootstrapper.rs b/state-sync/state-sync-driver/src/bootstrapper.rs index 45e4c4255bb65..59f01dc526653 100644 --- a/state-sync/state-sync-driver/src/bootstrapper.rs +++ b/state-sync/state-sync-driver/src/bootstrapper.rs @@ -39,6 +39,7 @@ pub const GENESIS_TRANSACTION_VERSION: u64 = 0; // The expected version of the g /// A simple container for verified epoch states and epoch ending ledger infos /// that have been fetched from the network. +#[derive(Clone)] pub(crate) struct VerifiedEpochStates { // If new epoch ending ledger infos have been fetched from the network fetched_epoch_ending_ledger_infos: bool, @@ -142,10 +143,10 @@ impl VerifiedEpochStates { // Verify we haven't missed the waypoint if ledger_info_version > waypoint_version { - return Err(Error::VerificationError( - format!("Failed to verify the waypoint: ledger info version is too high! Waypoint version: {:?}, ledger info version: {:?}", - waypoint_version, ledger_info_version) - )); + panic!( + "Failed to verify the waypoint: ledger info version is too high! Waypoint version: {:?}, ledger info version: {:?}", + waypoint_version, ledger_info_version + ); } // Check if we've found the ledger info corresponding to the waypoint version @@ -153,10 +154,10 @@ impl VerifiedEpochStates { match waypoint.verify(ledger_info) { Ok(()) => self.set_verified_waypoint(waypoint_version), Err(error) => { - return Err(Error::VerificationError( - format!("Failed to verify the waypoint: {:?}! Waypoint: {:?}, given ledger info: {:?}", - error, waypoint, ledger_info) - )); + panic!( + "Failed to verify the waypoint: {:?}! Waypoint: {:?}, given ledger info: {:?}", + error, waypoint, ledger_info + ); }, } } @@ -862,7 +863,11 @@ impl< self.verified_epoch_states .set_fetched_epoch_ending_ledger_infos(); } else { - return Err(Error::AdvertisedDataError("Our waypoint is unverified, but there's no higher epoch ending ledger infos advertised!".into())); + return Err(Error::AdvertisedDataError(format!( + "Our waypoint is unverified, but there's no higher epoch ending ledger infos \ + advertised! Highest local epoch end: {:?}, highest advertised epoch end: {:?}", + highest_local_epoch_end, highest_advertised_epoch_end + ))); }; Ok(()) @@ -1552,4 +1557,10 @@ impl< pub(crate) fn get_state_value_syncer(&mut self) -> &mut StateValueSyncer { &mut self.state_value_syncer } + + /// Manually sets the waypoint for testing purposes + #[cfg(test)] + pub(crate) fn set_waypoint(&mut self, waypoint: Waypoint) { + self.driver_configuration.waypoint = waypoint; + } } diff --git a/state-sync/state-sync-driver/src/tests/bootstrapper.rs b/state-sync/state-sync-driver/src/tests/bootstrapper.rs index 790c42cc39650..a6191d0752e43 100644 --- a/state-sync/state-sync-driver/src/tests/bootstrapper.rs +++ b/state-sync/state-sync-driver/src/tests/bootstrapper.rs @@ -752,6 +752,122 @@ async fn test_data_stream_transactions_or_outputs_fallback() { #[tokio::test] async fn test_fetch_epoch_ending_ledger_infos() { + // Create a driver configuration + let mut driver_configuration = create_full_node_driver_configuration(); + + // Update the driver configuration to use a waypoint in the future + let waypoint_version = 100; + let waypoint_epoch = 100; + let waypoint = create_random_epoch_ending_ledger_info(waypoint_version, waypoint_epoch); + driver_configuration.waypoint = Waypoint::new_any(waypoint.ledger_info()); + + // Create the mock streaming client + let mut mock_streaming_client = create_mock_streaming_client(); + let (mut notification_sender, data_stream_listener) = create_data_stream_listener(); + mock_streaming_client + .expect_get_all_epoch_ending_ledger_infos() + .with(eq(1)) + .return_once(move |_| Ok(data_stream_listener)); + mock_streaming_client + .expect_terminate_stream_with_feedback() + .return_const(Ok(())); + + // Create the bootstrapper + let (mut bootstrapper, _) = + create_bootstrapper(driver_configuration, mock_streaming_client, None, true); + + // Create a global data summary where epoch 100 has ended + let global_data_summary = + create_global_summary_with_version(waypoint_epoch, waypoint_version + 1); + + // Drive progress to initialize the epoch ending data stream + drive_progress(&mut bootstrapper, &global_data_summary, false) + .await + .unwrap(); + + // Create the first set of epoch ending ledger infos and send them across the stream + let num_ledger_infos_to_send = waypoint_epoch / 2; + let mut epoch_ending_ledger_infos = vec![]; + for index in 0..num_ledger_infos_to_send { + epoch_ending_ledger_infos.push(create_random_epoch_ending_ledger_info(index, index)); + } + let data_notification = DataNotification::new( + 0, + DataPayload::EpochEndingLedgerInfos(epoch_ending_ledger_infos.clone()), + ); + notification_sender.send(data_notification).await.unwrap(); + + // Drive progress to process the first set of epoch ending ledger infos + let error = drive_progress(&mut bootstrapper, &global_data_summary, false) + .await + .unwrap_err(); + assert_matches!(error, Error::DataStreamNotificationTimeout(_)); + + // Verify we're not bootstrapped yet + assert!(!bootstrapper.is_bootstrapped()); + + // Verify the bootstrapper has not fetched all ledger infos or verified the waypoint + let verified_epoch_states = bootstrapper.get_verified_epoch_states().clone(); + assert!(!verified_epoch_states.fetched_epoch_ending_ledger_infos()); + assert!(!verified_epoch_states.verified_waypoint()); + + // Verify the epoch states contains the first set of epoch ending ledger infos + let verified_ledger_infos = verified_epoch_states.all_epoch_ending_ledger_infos(); + assert_eq!(verified_ledger_infos.len() as u64, num_ledger_infos_to_send); + for epoch_ending_ledger_info in epoch_ending_ledger_infos { + assert!(verified_ledger_infos.contains(&epoch_ending_ledger_info)); + } + + // Create the second set of epoch ending ledger infos and send them across the stream + let mut epoch_ending_ledger_infos = vec![]; + for index in num_ledger_infos_to_send..waypoint_epoch + 1 { + epoch_ending_ledger_infos.push(create_random_epoch_ending_ledger_info(index, index)); + } + let data_notification = DataNotification::new( + 1, + DataPayload::EpochEndingLedgerInfos(epoch_ending_ledger_infos.clone()), + ); + notification_sender.send(data_notification).await.unwrap(); + + // Artificially overwrite the waypoint hash so that verification passes + let last_ledger_info = epoch_ending_ledger_infos.last().unwrap().ledger_info(); + bootstrapper.set_waypoint(Waypoint::new_any(last_ledger_info)); + + // Drive progress to process the second set of epoch ending ledger infos + let error = drive_progress(&mut bootstrapper, &global_data_summary, false) + .await + .unwrap_err(); + assert_matches!(error, Error::DataStreamNotificationTimeout(_)); + + // Ensure the bootstrapper verified the waypoint + let verified_epoch_states = bootstrapper.get_verified_epoch_states().clone(); + assert!(verified_epoch_states.verified_waypoint()); + + // Verify the epoch states contains all epoch ending ledger infos + let verified_ledger_infos = verified_epoch_states.all_epoch_ending_ledger_infos(); + assert_eq!(verified_ledger_infos.len() as u64, waypoint_epoch + 1); + for epoch_ending_ledger_info in epoch_ending_ledger_infos { + assert!(verified_ledger_infos.contains(&epoch_ending_ledger_info)); + } + + // Send the end of stream notification + let data_notification = DataNotification::new(2, DataPayload::EndOfStream); + notification_sender.send(data_notification).await.unwrap(); + + // Drive progress to process the end of stream notification + for _ in 0..2 { + drive_progress(&mut bootstrapper, &global_data_summary, false) + .await + .unwrap(); + } + + // Verify the bootstrapper has fetched all ledger infos + let verified_epoch_states = bootstrapper.get_verified_epoch_states().clone(); + assert!(verified_epoch_states.fetched_epoch_ending_ledger_infos()); +} + +#[tokio::test] +async fn test_fetch_epoch_ending_ledger_infos_timeout() { // Create a driver configuration with a genesis waypoint and a stream timeout of 1 second let mut driver_configuration = create_full_node_driver_configuration(); driver_configuration.config.max_stream_wait_time_ms = 1000; @@ -787,6 +903,56 @@ async fn test_fetch_epoch_ending_ledger_infos() { assert_matches!(error, Error::DataStreamNotificationTimeout(_)); } +#[tokio::test] +#[should_panic(expected = "Failed to verify the waypoint: Waypoint value mismatch")] +async fn test_fetch_epoch_ending_ledger_infos_waypoint_mismatch() { + // Create a driver configuration + let mut driver_configuration = create_full_node_driver_configuration(); + + // Update the driver configuration to use a waypoint in the future + let waypoint_version = 100; + let waypoint_epoch = 100; + let waypoint = create_random_epoch_ending_ledger_info(waypoint_version, waypoint_epoch); + driver_configuration.waypoint = Waypoint::new_any(waypoint.ledger_info()); + + // Create the mock streaming client + let mut mock_streaming_client = create_mock_streaming_client(); + let (mut notification_sender, data_stream_listener) = create_data_stream_listener(); + mock_streaming_client + .expect_get_all_epoch_ending_ledger_infos() + .with(eq(1)) + .return_once(move |_| Ok(data_stream_listener)); + + // Create the bootstrapper + let (mut bootstrapper, _) = + create_bootstrapper(driver_configuration, mock_streaming_client, None, true); + + // Create a global data summary where epoch 100 has ended + let global_data_summary = + create_global_summary_with_version(waypoint_epoch, waypoint_version + 1); + + // Drive progress to initialize the epoch ending data stream + drive_progress(&mut bootstrapper, &global_data_summary, false) + .await + .unwrap(); + + // Create a full set of epoch ending ledger infos and send them across the stream + let mut epoch_ending_ledger_infos = vec![]; + for index in 0..waypoint_epoch + 1 { + epoch_ending_ledger_infos.push(create_random_epoch_ending_ledger_info(index, index)); + } + let data_notification = DataNotification::new( + 0, + DataPayload::EpochEndingLedgerInfos(epoch_ending_ledger_infos.clone()), + ); + notification_sender.send(data_notification).await.unwrap(); + + // Drive progress to process the set of epoch ending ledger infos and panic at the waypoint mismatch + drive_progress(&mut bootstrapper, &global_data_summary, false) + .await + .unwrap(); +} + #[tokio::test] async fn test_snapshot_sync_epoch_change() { // Create test data diff --git a/state-sync/state-sync-driver/src/tests/utils.rs b/state-sync/state-sync-driver/src/tests/utils.rs index f95b43a620aac..1a481e7323876 100644 --- a/state-sync/state-sync-driver/src/tests/utils.rs +++ b/state-sync/state-sync-driver/src/tests/utils.rs @@ -35,6 +35,7 @@ use aptos_types::{ TransactionAuxiliaryData, TransactionInfo, TransactionListWithProof, TransactionOutput, TransactionOutputListWithProof, TransactionPayload, TransactionStatus, Version, }, + validator_verifier::ValidatorVerifier, waypoint::Waypoint, write_set::WriteSet, }; @@ -145,14 +146,15 @@ pub fn create_random_epoch_ending_ledger_info( version: Version, epoch: Epoch, ) -> LedgerInfoWithSignatures { + let next_epoch_state = EpochState::new(epoch + 1, ValidatorVerifier::new(vec![])); let block_info = BlockInfo::new( epoch, 0, HashValue::zero(), HashValue::random(), version, - 0, - Some(EpochState::empty()), + version, + Some(next_epoch_state), ); let ledger_info = LedgerInfo::new(block_info, HashValue::random()); LedgerInfoWithSignatures::new(ledger_info, AggregateSignature::empty()) diff --git a/types/src/epoch_state.rs b/types/src/epoch_state.rs index b160d552ff964..f805253cc4c8d 100644 --- a/types/src/epoch_state.rs +++ b/types/src/epoch_state.rs @@ -23,6 +23,10 @@ pub struct EpochState { } impl EpochState { + pub fn new(epoch: u64, verifier: ValidatorVerifier) -> Self { + Self { epoch, verifier } + } + pub fn empty() -> Self { Self { epoch: 0, From 3d3ebad651f7939383a4e354335eb2a0c85f94ff Mon Sep 17 00:00:00 2001 From: Sital Kedia Date: Mon, 8 Apr 2024 15:27:12 -0700 Subject: [PATCH 24/36] [Emitter] Changes to support pluggable account type for keyless support (#12813) --- crates/transaction-emitter-lib/src/args.rs | 5 +- .../src/emitter/account_minter.rs | 48 +++----------- .../src/emitter/local_account_generator.rs | 66 +++++++++++++++++++ .../src/emitter/mod.rs | 31 +++++++-- .../transaction-emitter-lib/src/wrappers.rs | 5 +- crates/transaction-generator-lib/src/lib.rs | 9 +++ sdk/src/types.rs | 54 ++++++++++----- 7 files changed, 155 insertions(+), 63 deletions(-) create mode 100644 crates/transaction-emitter-lib/src/emitter/local_account_generator.rs diff --git a/crates/transaction-emitter-lib/src/args.rs b/crates/transaction-emitter-lib/src/args.rs index e570eaaf3660f..45fe819576cbb 100644 --- a/crates/transaction-emitter-lib/src/args.rs +++ b/crates/transaction-emitter-lib/src/args.rs @@ -5,7 +5,7 @@ use anyhow::{bail, format_err, Result}; use aptos_config::keys::ConfigKey; use aptos_crypto::{ed25519::Ed25519PrivateKey, encoding_type::EncodingType}; use aptos_sdk::types::chain_id::ChainId; -use aptos_transaction_generator_lib::args::TransactionTypeArg; +use aptos_transaction_generator_lib::{args::TransactionTypeArg, AccountType}; use clap::{ArgGroup, Parser}; use serde::{Deserialize, Serialize}; use std::{ @@ -138,6 +138,9 @@ pub struct EmitArgs { )] pub transaction_type: Vec, + #[clap(long, value_enum, default_value = "local", ignore_case = true)] + pub account_type: AccountType, + /// Number of copies of the modules that will be published, /// under separate accounts, creating independent contracts, /// removing contention. diff --git a/crates/transaction-emitter-lib/src/emitter/account_minter.rs b/crates/transaction-emitter-lib/src/emitter/account_minter.rs index 2932fe50b4407..a96e91d11eb1d 100644 --- a/crates/transaction-emitter-lib/src/emitter/account_minter.rs +++ b/crates/transaction-emitter-lib/src/emitter/account_minter.rs @@ -1,7 +1,7 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use crate::EmitJobRequest; +use crate::{emitter::local_account_generator::LocalAccountGenerator, EmitJobRequest}; use anyhow::{anyhow, bail, format_err, Context, Result}; use aptos_crypto::{ ed25519::{Ed25519PrivateKey, Ed25519PublicKey}, @@ -22,7 +22,7 @@ use core::{ cmp::min, result::Result::{Err, Ok}, }; -use futures::{future::try_join_all, StreamExt}; +use futures::StreamExt; use rand::{rngs::StdRng, Rng, SeedableRng}; use std::{ path::Path, @@ -250,6 +250,7 @@ impl<'t> AccountMinter<'t> { &mut self, txn_executor: &dyn ReliableTransactionSubmitter, req: &EmitJobRequest, + account_generator: Box, max_submit_batch_size: usize, local_accounts: Vec>, ) -> Result<()> { @@ -316,6 +317,7 @@ impl<'t> AccountMinter<'t> { .create_and_fund_seed_accounts( new_source_account, txn_executor, + account_generator, expected_num_seed_accounts, coins_per_seed_account, max_submit_batch_size, @@ -393,6 +395,7 @@ impl<'t> AccountMinter<'t> { &mut self, mut new_source_account: Option, txn_executor: &dyn ReliableTransactionSubmitter, + account_generator: Box, seed_account_num: usize, coins_per_seed_account: u64, max_submit_batch_size: usize, @@ -407,7 +410,9 @@ impl<'t> AccountMinter<'t> { while i < seed_account_num { let batch_size = min(max_submit_batch_size, seed_account_num - i); let mut rng = StdRng::from_rng(self.rng()).unwrap(); - let mut batch = gen_reusable_accounts(txn_executor, batch_size, &mut rng).await?; + let mut batch = account_generator + .gen_local_accounts(txn_executor, batch_size, &mut rng) + .await?; let txn_factory = &self.txn_factory; let create_requests: Vec<_> = batch .iter() @@ -546,43 +551,6 @@ async fn create_and_fund_new_accounts( Ok(()) } -pub async fn gen_reusable_accounts( - txn_executor: &dyn ReliableTransactionSubmitter, - num_accounts: usize, - rng: &mut R, -) -> Result> -where - R: rand_core::RngCore + ::rand_core::CryptoRng, -{ - let mut account_keys = vec![]; - let mut addresses = vec![]; - let mut i = 0; - while i < num_accounts { - let account_key = AccountKey::generate(rng); - addresses.push(account_key.authentication_key().account_address()); - account_keys.push(account_key); - i += 1; - } - let result_futures = addresses - .iter() - .map(|address| txn_executor.query_sequence_number(*address)) - .collect::>(); - let seq_nums: Vec<_> = try_join_all(result_futures).await?.into_iter().collect(); - - let accounts = account_keys - .into_iter() - .zip(seq_nums.into_iter()) - .map(|(account_key, sequence_number)| { - LocalAccount::new( - account_key.authentication_key().account_address(), - account_key, - sequence_number, - ) - }) - .collect(); - Ok(accounts) -} - pub fn create_and_fund_account_request( creation_account: &LocalAccount, amount: u64, diff --git a/crates/transaction-emitter-lib/src/emitter/local_account_generator.rs b/crates/transaction-emitter-lib/src/emitter/local_account_generator.rs new file mode 100644 index 0000000000000..6691a29cc58e1 --- /dev/null +++ b/crates/transaction-emitter-lib/src/emitter/local_account_generator.rs @@ -0,0 +1,66 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 +use aptos_sdk::types::{AccountKey, LocalAccount}; +use aptos_transaction_generator_lib::{AccountType, ReliableTransactionSubmitter}; +use async_trait::async_trait; +use futures::future::try_join_all; +use rand::rngs::StdRng; + +#[async_trait] +pub trait LocalAccountGenerator: Send + Sync { + async fn gen_local_accounts( + &self, + txn_executor: &dyn ReliableTransactionSubmitter, + num_accounts: usize, + rng: &mut StdRng, + ) -> anyhow::Result>; +} + +pub fn create_account_generator(account_type: AccountType) -> Box { + match account_type { + AccountType::Local => Box::new(PrivateKeyAccountGenerator), + _ => { + unimplemented!("Account type {:?} is not supported", account_type) + }, + } +} + +pub struct PrivateKeyAccountGenerator; + +#[async_trait] +impl LocalAccountGenerator for PrivateKeyAccountGenerator { + async fn gen_local_accounts( + &self, + txn_executor: &dyn ReliableTransactionSubmitter, + num_accounts: usize, + rng: &mut StdRng, + ) -> anyhow::Result> { + let mut account_keys = vec![]; + let mut addresses = vec![]; + let mut i = 0; + while i < num_accounts { + let account_key = AccountKey::generate(rng); + addresses.push(account_key.authentication_key().account_address()); + account_keys.push(account_key); + i += 1; + } + let result_futures = addresses + .iter() + .map(|address| txn_executor.query_sequence_number(*address)) + .collect::>(); + let seq_nums: Vec<_> = try_join_all(result_futures).await?.into_iter().collect(); + + let accounts = account_keys + .into_iter() + .zip(seq_nums) + .map(|(account_key, sequence_number)| { + LocalAccount::new( + account_key.authentication_key().account_address(), + account_key, + sequence_number, + ) + }) + .collect(); + Ok(accounts) + } +} diff --git a/crates/transaction-emitter-lib/src/emitter/mod.rs b/crates/transaction-emitter-lib/src/emitter/mod.rs index 0cdd7c29e19ca..fac4f8cbee1e1 100644 --- a/crates/transaction-emitter-lib/src/emitter/mod.rs +++ b/crates/transaction-emitter-lib/src/emitter/mod.rs @@ -2,12 +2,14 @@ // SPDX-License-Identifier: Apache-2.0 pub mod account_minter; +pub mod local_account_generator; pub mod stats; pub mod submission_worker; pub mod transaction_executor; use crate::emitter::{ - account_minter::{gen_reusable_accounts, AccountMinter, SourceAccountManager}, + account_minter::{AccountMinter, SourceAccountManager}, + local_account_generator::{create_account_generator, LocalAccountGenerator}, stats::{DynamicStatsTracking, TxnStats}, submission_worker::SubmissionWorker, transaction_executor::RestApiReliableTransactionSubmitter, @@ -23,7 +25,7 @@ use aptos_sdk::{ types::{transaction::SignedTransaction, LocalAccount}, }; use aptos_transaction_generator_lib::{ - create_txn_generator_creator, ReliableTransactionSubmitter, TransactionType, + create_txn_generator_creator, AccountType, ReliableTransactionSubmitter, TransactionType, }; use futures::future::{try_join_all, FutureExt}; use once_cell::sync::Lazy; @@ -141,7 +143,7 @@ pub struct EmitJobRequest { mode: EmitJobMode, transaction_mix_per_phase: Vec>, - + account_type: AccountType, max_gas_per_txn: u64, init_max_gas_per_txn: Option, @@ -181,6 +183,7 @@ impl Default for EmitJobRequest { mempool_backlog: 3000, }, transaction_mix_per_phase: vec![vec![(TransactionType::default(), 1)]], + account_type: AccountType::Local, max_gas_per_txn: aptos_global_constants::MAX_GAS_AMOUNT, gas_price: aptos_global_constants::GAS_UNIT_PRICE, init_max_gas_per_txn: None, @@ -277,6 +280,11 @@ impl EmitJobRequest { self } + pub fn account_type(mut self, account_type: AccountType) -> Self { + self.account_type = account_type; + self + } + pub fn get_num_phases(&self) -> usize { self.transaction_mix_per_phase.len() } @@ -693,9 +701,12 @@ impl TxnEmitter { usize::try_from(init_expiration_time / req.init_retry_interval.as_secs()).unwrap(); let seed = req.account_minter_seed.unwrap_or_else(|| self.rng.gen()); + let account_generator = create_account_generator(req.account_type); + let mut all_accounts = create_accounts( root_account, &init_txn_factory, + account_generator, &req, mode_params.max_submit_batch_size, req.skip_minting_accounts, @@ -1120,6 +1131,7 @@ pub fn parse_seed(seed_string: &str) -> [u8; 32] { pub async fn create_accounts( root_account: &LocalAccount, txn_factory: &TransactionFactory, + account_generator: Box, req: &EmitJobRequest, max_submit_batch_size: usize, skip_minting_accounts: bool, @@ -1151,7 +1163,10 @@ pub async fn create_accounts( let mut rng = StdRng::from_seed(seed); - let accounts = gen_reusable_accounts(&txn_executor, num_accounts, &mut rng).await?; + let accounts = account_generator + .gen_local_accounts(&txn_executor, num_accounts, &mut rng) + .await?; + info!("Generated re-usable accounts for seed {:?}", seed); let all_accounts_already_exist = accounts.iter().all(|account| account.sequence_number() > 0); @@ -1170,7 +1185,13 @@ pub async fn create_accounts( if !skip_minting_accounts { let accounts: Vec<_> = accounts.into_iter().map(Arc::new).collect(); account_minter - .create_and_fund_accounts(&txn_executor, req, max_submit_batch_size, accounts.clone()) + .create_and_fund_accounts( + &txn_executor, + req, + account_generator, + max_submit_batch_size, + accounts.clone(), + ) .await?; let accounts: Vec<_> = accounts .into_iter() diff --git a/crates/transaction-emitter-lib/src/wrappers.rs b/crates/transaction-emitter-lib/src/wrappers.rs index a25800e8f983a..9f6659e5e9b98 100644 --- a/crates/transaction-emitter-lib/src/wrappers.rs +++ b/crates/transaction-emitter-lib/src/wrappers.rs @@ -5,8 +5,8 @@ use crate::{ args::{ClusterArgs, EmitArgs}, cluster::Cluster, emitter::{ - create_accounts, parse_seed, stats::TxnStats, EmitJobMode, EmitJobRequest, NumAccountsMode, - TxnEmitter, + create_accounts, local_account_generator::PrivateKeyAccountGenerator, parse_seed, + stats::TxnStats, EmitJobMode, EmitJobRequest, NumAccountsMode, TxnEmitter, }, instance::Instance, CreateAccountsArgs, @@ -196,6 +196,7 @@ pub async fn create_accounts_command( create_accounts( &coin_source_account, &txn_factory, + Box::new(PrivateKeyAccountGenerator), &emit_job_request, DEFAULT_MAX_SUBMIT_TRANSACTION_BATCH_SIZE, false, diff --git a/crates/transaction-generator-lib/src/lib.rs b/crates/transaction-generator-lib/src/lib.rs index a625f795acd9c..364c6f8421eef 100644 --- a/crates/transaction-generator-lib/src/lib.rs +++ b/crates/transaction-generator-lib/src/lib.rs @@ -13,7 +13,9 @@ use aptos_sdk::{ }; use args::TransactionTypeArg; use async_trait::async_trait; +use clap::{Parser, ValueEnum}; use rand::{rngs::StdRng, seq::SliceRandom, Rng}; +use serde::{Deserialize, Serialize}; use std::{ collections::HashMap, sync::{ @@ -86,6 +88,13 @@ pub enum TransactionType { }, } +#[derive(Debug, Copy, Clone, ValueEnum, Default, Deserialize, Parser, Serialize)] +pub enum AccountType { + #[default] + Local, + Keyless, +} + #[derive(Debug, Copy, Clone)] pub enum WorkflowKind { CreateMintBurn { count: usize, creation_balance: u64 }, diff --git a/sdk/src/types.rs b/sdk/src/types.rs index 456bb2524312c..ba9a152d86819 100644 --- a/sdk/src/types.rs +++ b/sdk/src/types.rs @@ -27,6 +27,28 @@ use std::{ time::{Duration, SystemTime, UNIX_EPOCH}, }; +#[derive(Debug)] +enum LocalAccountAuthenticator { + PrivateKey(AccountKey), + // TODO: Add support for keyless authentication +} + +impl LocalAccountAuthenticator { + pub fn sign_transaction(&self, txn: RawTransaction) -> SignedTransaction { + match self { + LocalAccountAuthenticator::PrivateKey(key) => txn + .sign(key.private_key(), key.public_key().clone()) + .expect("Signing a txn can't fail") + .into_inner(), + } + } +} +impl> From for LocalAccountAuthenticator { + fn from(key: T) -> Self { + Self::PrivateKey(key.into()) + } +} + /// LocalAccount represents an account on the Aptos blockchain. Internally it /// holds the private / public key pair and the address of the account. You can /// use this struct to help transact with the blockchain, e.g. by generating a @@ -35,8 +57,8 @@ use std::{ pub struct LocalAccount { /// Address of the account. address: AccountAddress, - /// Authentication key of the account. - key: AccountKey, + /// Authenticator of the account + auth: LocalAccountAuthenticator, /// Latest known sequence number of the account, it can be different from validator. sequence_number: AtomicU64, } @@ -48,7 +70,7 @@ impl LocalAccount { pub fn new>(address: AccountAddress, key: T, sequence_number: u64) -> Self { Self { address, - key: key.into(), + auth: LocalAccountAuthenticator::from(key), sequence_number: AtomicU64::new(sequence_number), } } @@ -69,11 +91,7 @@ impl LocalAccount { let key = AccountKey::from(Ed25519PrivateKey::try_from(key.as_bytes().as_ref())?); let address = key.authentication_key().account_address(); - Ok(Self { - address, - key, - sequence_number: AtomicU64::new(sequence_number), - }) + Ok(Self::new(address, key, sequence_number)) } /// Generate a new account locally. Note: This function does not actually @@ -90,9 +108,7 @@ impl LocalAccount { } pub fn sign_transaction(&self, txn: RawTransaction) -> SignedTransaction { - txn.sign(self.private_key(), self.public_key().clone()) - .expect("Signing a txn can't fail") - .into_inner() + self.auth.sign_transaction(txn) } pub fn sign_with_transaction_builder(&self, builder: TransactionBuilder) -> SignedTransaction { @@ -165,15 +181,21 @@ impl LocalAccount { } pub fn private_key(&self) -> &Ed25519PrivateKey { - self.key.private_key() + match &self.auth { + LocalAccountAuthenticator::PrivateKey(key) => key.private_key(), + } } pub fn public_key(&self) -> &Ed25519PublicKey { - self.key.public_key() + match &self.auth { + LocalAccountAuthenticator::PrivateKey(key) => key.public_key(), + } } pub fn authentication_key(&self) -> AuthenticationKey { - self.key.authentication_key() + match &self.auth { + LocalAccountAuthenticator::PrivateKey(key) => key.authentication_key(), + } } pub fn sequence_number(&self) -> u64 { @@ -194,7 +216,9 @@ impl LocalAccount { } pub fn rotate_key>(&mut self, new_key: T) -> AccountKey { - std::mem::replace(&mut self.key, new_key.into()) + match &mut self.auth { + LocalAccountAuthenticator::PrivateKey(key) => std::mem::replace(key, new_key.into()), + } } pub fn received_event_key(&self) -> EventKey { From 1de391c3589cf2d07cb423a73c4a2a6caa299ebf Mon Sep 17 00:00:00 2001 From: Alan Luong Date: Mon, 8 Apr 2024 18:51:03 -0400 Subject: [PATCH 25/36] use one forge namespace for each branch (#12633) --- .github/workflows/forge-stable.yaml | 43 +++++++++++++++++++---------- testsuite/forge.py | 8 +++++- 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/.github/workflows/forge-stable.yaml b/.github/workflows/forge-stable.yaml index e63a78eb4c13e..a50b935fe6f75 100644 --- a/.github/workflows/forge-stable.yaml +++ b/.github/workflows/forge-stable.yaml @@ -45,6 +45,7 @@ jobs: outputs: IMAGE_TAG: ${{ steps.get-docker-image-tag.outputs.IMAGE_TAG }} BRANCH: ${{ steps.determine-test-branch.outputs.BRANCH }} + BRANCH_HASH: ${{ steps.hash-branch.outputs.BRANCH_HASH }} steps: - uses: actions/checkout@v3 @@ -69,6 +70,20 @@ jobs: echo "BRANCH=${{ inputs.GIT_SHA }}" >> $GITHUB_OUTPUT fi + # Use the branch hash instead of the full branch name to stay under kubernetes namespace length limit + - name: Hash the branch + id: hash-branch + run: | + # If BRANCH is empty, default to "main" + if [ -z "${{ steps.determine-test-branch.outputs.BRANCH }}" ]; then + BRANCH="main" + else + BRANCH="${{ steps.determine-test-branch.outputs.BRANCH }}" + fi + + # Hashing the branch name + echo "BRANCH_HASH=$(echo -n "$BRANCH" | sha256sum | cut -c1-10)" >> $GITHUB_OUTPUT + - uses: aptos-labs/aptos-core/.github/actions/check-aptos-core@main with: cancel-workflow: ${{ github.event_name == 'schedule' }} # Cancel the workflow if it is scheduled on a fork @@ -110,7 +125,7 @@ jobs: secrets: inherit with: IMAGE_TAG: ${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} - FORGE_NAMESPACE: forge-realistic-env-max-load-long-${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} + FORGE_NAMESPACE: forge-realistic-env-max-load-long-${{ needs.determine-test-metadata.outputs.BRANCH_HASH }} FORGE_RUNNER_DURATION_SECS: 7200 # Run for 2 hours FORGE_TEST_SUITE: realistic_env_max_load_large POST_TO_SLACK: true @@ -122,7 +137,7 @@ jobs: secrets: inherit with: IMAGE_TAG: ${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} - FORGE_NAMESPACE: forge-realistic-env-load-sweep-${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} + FORGE_NAMESPACE: forge-realistic-env-load-sweep-${{ needs.determine-test-metadata.outputs.BRANCH_HASH }} FORGE_RUNNER_DURATION_SECS: 1500 # Run for 25 minutes (5 tests, each for 300 seconds) FORGE_TEST_SUITE: realistic_env_load_sweep POST_TO_SLACK: true @@ -134,7 +149,7 @@ jobs: secrets: inherit with: IMAGE_TAG: ${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} - FORGE_NAMESPACE: forge-realistic-env-workload-sweep-${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} + FORGE_NAMESPACE: forge-realistic-env-workload-sweep-${{ needs.determine-test-metadata.outputs.BRANCH_HASH }} FORGE_RUNNER_DURATION_SECS: 1600 # Run for 26 minutes (4 tests, each for 400 seconds) FORGE_TEST_SUITE: realistic_env_workload_sweep POST_TO_SLACK: true @@ -146,7 +161,7 @@ jobs: secrets: inherit with: IMAGE_TAG: ${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} - FORGE_NAMESPACE: forge-realistic-env-graceful-overload-${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} + FORGE_NAMESPACE: forge-realistic-env-graceful-overload-${{ needs.determine-test-metadata.outputs.BRANCH_HASH }} FORGE_RUNNER_DURATION_SECS: 1200 # Run for 20 minutes FORGE_TEST_SUITE: realistic_env_graceful_overload POST_TO_SLACK: true @@ -158,7 +173,7 @@ jobs: secrets: inherit with: IMAGE_TAG: ${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} - FORGE_NAMESPACE: forge-realistic-network-tuned-for-throughput-${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} + FORGE_NAMESPACE: forge-realistic-network-tuned-for-throughput-${{ needs.determine-test-metadata.outputs.BRANCH_HASH }} FORGE_RUNNER_DURATION_SECS: 900 # Run for 15 minutes FORGE_TEST_SUITE: realistic_network_tuned_for_throughput FORGE_ENABLE_PERFORMANCE: true @@ -173,7 +188,7 @@ jobs: secrets: inherit with: IMAGE_TAG: ${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} - FORGE_NAMESPACE: forge-consensus-stress-test-${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} + FORGE_NAMESPACE: forge-consensus-stress-test-${{ needs.determine-test-metadata.outputs.BRANCH_HASH }} FORGE_RUNNER_DURATION_SECS: 2400 # Run for 40 minutes FORGE_TEST_SUITE: consensus_stress_test POST_TO_SLACK: true @@ -185,7 +200,7 @@ jobs: secrets: inherit with: IMAGE_TAG: ${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} - FORGE_NAMESPACE: forge-workload-mix-test-${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} + FORGE_NAMESPACE: forge-workload-mix-test-${{ needs.determine-test-metadata.outputs.BRANCH_HASH }} FORGE_RUNNER_DURATION_SECS: 900 # Run for 15 minutes FORGE_TEST_SUITE: workload_mix POST_TO_SLACK: true @@ -197,7 +212,7 @@ jobs: secrets: inherit with: IMAGE_TAG: ${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} - FORGE_NAMESPACE: forge-continuous-e2e-single-vfn-${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} + FORGE_NAMESPACE: forge-continuous-e2e-single-vfn-${{ needs.determine-test-metadata.outputs.BRANCH_HASH }} FORGE_RUNNER_DURATION_SECS: 480 # Run for 8 minutes FORGE_TEST_SUITE: single_vfn_perf POST_TO_SLACK: true @@ -209,7 +224,7 @@ jobs: secrets: inherit with: IMAGE_TAG: ${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} - FORGE_NAMESPACE: forge-haproxy-${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} + FORGE_NAMESPACE: forge-haproxy-${{ needs.determine-test-metadata.outputs.BRANCH_HASH }} FORGE_RUNNER_DURATION_SECS: 600 # Run for 10 minutes FORGE_ENABLE_HAPROXY: true FORGE_TEST_SUITE: realistic_env_max_load @@ -222,7 +237,7 @@ jobs: secrets: inherit with: IMAGE_TAG: ${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} - FORGE_NAMESPACE: forge-fullnode-reboot-stress-${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} + FORGE_NAMESPACE: forge-fullnode-reboot-stress-${{ needs.determine-test-metadata.outputs.BRANCH_HASH }} FORGE_RUNNER_DURATION_SECS: 1800 # Run for 30 minutes FORGE_TEST_SUITE: fullnode_reboot_stress_test POST_TO_SLACK: true @@ -235,7 +250,7 @@ jobs: uses: aptos-labs/aptos-core/.github/workflows/workflow-run-forge.yaml@main secrets: inherit with: - FORGE_NAMESPACE: forge-compat-${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} + FORGE_NAMESPACE: forge-compat-${{ needs.determine-test-metadata.outputs.BRANCH_HASH }} FORGE_RUNNER_DURATION_SECS: 300 # Run for 5 minutes # This will upgrade from testnet branch to the latest main FORGE_TEST_SUITE: compat @@ -252,7 +267,7 @@ jobs: secrets: inherit with: IMAGE_TAG: ${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} - FORGE_NAMESPACE: forge-changing-working-quorum-test-${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} + FORGE_NAMESPACE: forge-changing-working-quorum-test-${{ needs.determine-test-metadata.outputs.BRANCH_HASH }} FORGE_RUNNER_DURATION_SECS: 1200 # Run for 20 minutes FORGE_TEST_SUITE: changing_working_quorum_test POST_TO_SLACK: true @@ -265,7 +280,7 @@ jobs: secrets: inherit with: IMAGE_TAG: ${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} - FORGE_NAMESPACE: forge-changing-working-quorum-test-high-load-${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} + FORGE_NAMESPACE: forge-changing-working-quorum-test-high-load-${{ needs.determine-test-metadata.outputs.BRANCH_HASH }} FORGE_RUNNER_DURATION_SECS: 900 # Run for 15 minutes FORGE_TEST_SUITE: changing_working_quorum_test_high_load POST_TO_SLACK: true @@ -279,7 +294,7 @@ jobs: secrets: inherit with: IMAGE_TAG: ${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} - FORGE_NAMESPACE: forge-pfn-const-tps-with-realistic-env-${{ needs.determine-test-metadata.outputs.IMAGE_TAG }} + FORGE_NAMESPACE: forge-pfn-const-tps-with-realistic-env-${{ needs.determine-test-metadata.outputs.BRANCH_HASH }} FORGE_RUNNER_DURATION_SECS: 900 # Run for 15 minutes FORGE_TEST_SUITE: pfn_const_tps_with_realistic_env POST_TO_SLACK: true diff --git a/testsuite/forge.py b/testsuite/forge.py index 67850bed4069d..ad50d0d5c5680 100644 --- a/testsuite/forge.py +++ b/testsuite/forge.py @@ -1249,6 +1249,11 @@ async def run_multiple( ) +def seeded_random_choice(namespace: str, cluster_names: Sequence[str]) -> str: + random.seed(namespace) + return random.choice(cluster_names) + + @main.command() # output files @envoption("FORGE_OUTPUT") @@ -1366,6 +1371,7 @@ def test( forge_namespace = f"forge-{processes.user()}-{time.epoch()}" assert forge_namespace is not None, "Forge namespace is required" + assert len(forge_namespace) <= 63, "Forge namespace must be 63 characters or less" forge_namespace = sanitize_forge_resource_name(forge_namespace) @@ -1418,7 +1424,7 @@ def test( # Perform cluster selection if not forge_cluster_name or balance_clusters: cluster_names = config.get("enabled_clusters") - forge_cluster_name = random.choice(cluster_names) + forge_cluster_name = seeded_random_choice(forge_namespace, cluster_names) assert forge_cluster_name, "Forge cluster name is required" From 8ff4788867a6a7b407ed0260bc63b5354ea0f267 Mon Sep 17 00:00:00 2001 From: Alden Hu Date: Tue, 9 Apr 2024 09:43:29 -0700 Subject: [PATCH 26/36] single-node-performance: update expected tps (#12826) --- testsuite/single_node_performance.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/testsuite/single_node_performance.py b/testsuite/single_node_performance.py index 116e6c641ab07..933576b031e69 100755 --- a/testsuite/single_node_performance.py +++ b/testsuite/single_node_performance.py @@ -136,10 +136,10 @@ class RunGroupConfig: RunGroupConfig(expected_tps=1300, key=RunGroupKey("token-v1nft-mint-and-transfer-parallel"), included_in=Flow(0)), RunGroupConfig(expected_tps=5300, key=RunGroupKey("token-v1nft-mint-and-transfer-parallel", module_working_set_size=20), included_in=Flow(0)), - RunGroupConfig(expected_tps=13800, key=RunGroupKey("coin-init-and-mint", module_working_set_size=1), included_in=LAND_BLOCKING_AND_C), - RunGroupConfig(expected_tps=11400, key=RunGroupKey("coin-init-and-mint", module_working_set_size=20), included_in=Flow.CONTINUOUS), - RunGroupConfig(expected_tps=1500, key=RunGroupKey("fungible-asset-mint", module_working_set_size=1), included_in=LAND_BLOCKING_AND_C), - RunGroupConfig(expected_tps=7500, key=RunGroupKey("fungible-asset-mint", module_working_set_size=20), included_in=Flow.CONTINUOUS), + RunGroupConfig(expected_tps=14500, key=RunGroupKey("coin-init-and-mint", module_working_set_size=1), included_in=LAND_BLOCKING_AND_C), + RunGroupConfig(expected_tps=12000, key=RunGroupKey("coin-init-and-mint", module_working_set_size=20), included_in=Flow.CONTINUOUS), + RunGroupConfig(expected_tps=1590, key=RunGroupKey("fungible-asset-mint", module_working_set_size=1), included_in=LAND_BLOCKING_AND_C), + RunGroupConfig(expected_tps=7900, key=RunGroupKey("fungible-asset-mint", module_working_set_size=20), included_in=Flow.CONTINUOUS), # RunGroupConfig(expected_tps=1000, key=RunGroupKey("token-v1ft-mint-and-store"), included_in=Flow(0)), # RunGroupConfig(expected_tps=1000, key=RunGroupKey("token-v1nft-mint-and-store-sequential"), included_in=Flow(0)), From f7735083ae598fc220efd9b4f59eb32e0490aed9 Mon Sep 17 00:00:00 2001 From: larry-aptos <112209412+larry-aptos@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:16:14 -0700 Subject: [PATCH 27/36] Change the compression to lz4 on main (#12747) --- Cargo.lock | 2 +- .../indexer-grpc-cache-worker/src/worker.rs | 2 +- .../indexer-grpc-data-service/src/config.rs | 2 +- .../indexer-grpc-file-store/src/processor.rs | 17 +++- .../indexer-grpc-utils/Cargo.toml | 2 +- .../src/compression_util.rs | 94 ++++++++++--------- .../src/file_store_operator/gcs.rs | 2 +- .../src/file_store_operator/local.rs | 2 +- 8 files changed, 70 insertions(+), 53 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bd85b5e59dfde..46cab3b23468b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2166,9 +2166,9 @@ dependencies = [ "chrono", "cloud-storage", "dashmap", - "flate2", "futures", "itertools 0.12.1", + "lz4", "once_cell", "prometheus", "prost 0.12.3", diff --git a/ecosystem/indexer-grpc/indexer-grpc-cache-worker/src/worker.rs b/ecosystem/indexer-grpc/indexer-grpc-cache-worker/src/worker.rs index 051adfaca691a..2af05115f8de5 100644 --- a/ecosystem/indexer-grpc/indexer-grpc-cache-worker/src/worker.rs +++ b/ecosystem/indexer-grpc/indexer-grpc-cache-worker/src/worker.rs @@ -80,7 +80,7 @@ impl Worker { enable_cache_compression: bool, ) -> Result { let cache_storage_format = if enable_cache_compression { - StorageFormat::GzipCompressedProto + StorageFormat::Lz4CompressedProto } else { StorageFormat::Base64UncompressedProto }; diff --git a/ecosystem/indexer-grpc/indexer-grpc-data-service/src/config.rs b/ecosystem/indexer-grpc/indexer-grpc-data-service/src/config.rs index 8e66977538873..71460c361f1fa 100644 --- a/ecosystem/indexer-grpc/indexer-grpc-data-service/src/config.rs +++ b/ecosystem/indexer-grpc/indexer-grpc-data-service/src/config.rs @@ -134,7 +134,7 @@ impl RunnableConfig for IndexerGrpcDataServiceConfig { .map_err(|e| anyhow::anyhow!("Failed to build reflection service: {}", e))?; let cache_storage_format: StorageFormat = if self.enable_cache_compression { - StorageFormat::GzipCompressedProto + StorageFormat::Lz4CompressedProto } else { StorageFormat::Base64UncompressedProto }; diff --git a/ecosystem/indexer-grpc/indexer-grpc-file-store/src/processor.rs b/ecosystem/indexer-grpc/indexer-grpc-file-store/src/processor.rs index 82dc8b0938836..1d875da609e83 100644 --- a/ecosystem/indexer-grpc/indexer-grpc-file-store/src/processor.rs +++ b/ecosystem/indexer-grpc/indexer-grpc-file-store/src/processor.rs @@ -18,6 +18,7 @@ use tracing::debug; // If the version is ahead of the cache head, retry after a short sleep. const AHEAD_OF_CACHE_SLEEP_DURATION_IN_MILLIS: u64 = 100; const SERVICE_TYPE: &str = "file_worker"; +const MAX_CONCURRENT_BATCHES: usize = 50; /// Processor tails the data in cache and stores the data in file store. pub struct Processor { @@ -34,7 +35,7 @@ impl Processor { enable_cache_compression: bool, ) -> Result { let cache_storage_format = if enable_cache_compression { - StorageFormat::GzipCompressedProto + StorageFormat::Lz4CompressedProto } else { StorageFormat::Base64UncompressedProto }; @@ -132,8 +133,17 @@ impl Processor { while start_version + (FILE_ENTRY_TRANSACTION_COUNT) < cache_worker_latest { batches.push(start_version); start_version += FILE_ENTRY_TRANSACTION_COUNT; + if batches.len() >= MAX_CONCURRENT_BATCHES { + break; + } } + tracing::info!( + batch_start_version = batch_start_version, + cache_worker_latest = cache_worker_latest, + batches = ?batches, + "Filestore processor loop" + ); // we're too close to the head if batches.is_empty() { debug!( @@ -150,6 +160,7 @@ impl Processor { // Create thread and fetch transactions let mut tasks = vec![]; + for start_version in batches { let mut cache_operator_clone = self.cache_operator.clone(); let mut file_store_operator_clone = self.file_store_operator.clone_box(); @@ -172,7 +183,9 @@ impl Processor { Some(FILE_ENTRY_TRANSACTION_COUNT as i64), None, ); - + for (i, txn) in transactions.iter().enumerate() { + assert_eq!(txn.version, start_version + i as u64); + } let upload_start_time = std::time::Instant::now(); let (start, end) = file_store_operator_clone .upload_transaction_batch(chain_id, transactions) diff --git a/ecosystem/indexer-grpc/indexer-grpc-utils/Cargo.toml b/ecosystem/indexer-grpc/indexer-grpc-utils/Cargo.toml index 50a1c31a8f636..2c0516ddda804 100644 --- a/ecosystem/indexer-grpc/indexer-grpc-utils/Cargo.toml +++ b/ecosystem/indexer-grpc/indexer-grpc-utils/Cargo.toml @@ -22,9 +22,9 @@ base64 = { workspace = true } chrono = { workspace = true } cloud-storage = { workspace = true } dashmap = { workspace = true } -flate2 = { workspace = true } futures = { workspace = true } itertools = { workspace = true } +lz4 = { workspace = true } once_cell = { workspace = true } prometheus = { workspace = true } prost = { workspace = true } diff --git a/ecosystem/indexer-grpc/indexer-grpc-utils/src/compression_util.rs b/ecosystem/indexer-grpc/indexer-grpc-utils/src/compression_util.rs index 92094a1be1d5f..07f528e6df124 100644 --- a/ecosystem/indexer-grpc/indexer-grpc-utils/src/compression_util.rs +++ b/ecosystem/indexer-grpc/indexer-grpc-utils/src/compression_util.rs @@ -3,17 +3,17 @@ use crate::default_file_storage_format; use aptos_protos::{indexer::v1::TransactionsInStorage, transaction::v1::Transaction}; -use flate2::read::{GzDecoder, GzEncoder}; +use lz4::{Decoder, EncoderBuilder}; use prost::Message; use ripemd::{Digest, Ripemd128}; use serde::{Deserialize, Serialize}; -use std::io::Read; +use std::io::{Read, Write}; pub const FILE_ENTRY_TRANSACTION_COUNT: u64 = 1000; #[derive(Serialize, Deserialize, Debug, Copy, Clone, Eq, PartialEq)] pub enum StorageFormat { - GzipCompressedProto, + Lz4CompressedProto, // Only used for legacy file format. // Use by cache only. Base64UncompressedProto, @@ -66,7 +66,7 @@ impl FileStoreMetadata { } pub enum CacheEntry { - GzipCompressionProto(Vec), + Lz4CompressionProto(Vec), // Only used for legacy cache entry. Base64UncompressedProto(Vec), } @@ -74,7 +74,7 @@ pub enum CacheEntry { impl CacheEntry { pub fn new(bytes: Vec, storage_format: StorageFormat) -> Self { match storage_format { - StorageFormat::GzipCompressedProto => Self::GzipCompressionProto(bytes), + StorageFormat::Lz4CompressedProto => Self::Lz4CompressionProto(bytes), // Legacy format. StorageFormat::Base64UncompressedProto => Self::Base64UncompressedProto(bytes), StorageFormat::JsonBase64UncompressedProto => { @@ -85,14 +85,14 @@ impl CacheEntry { pub fn into_inner(self) -> Vec { match self { - CacheEntry::GzipCompressionProto(bytes) => bytes, + CacheEntry::Lz4CompressionProto(bytes) => bytes, CacheEntry::Base64UncompressedProto(bytes) => bytes, } } pub fn size(&self) -> usize { match self { - CacheEntry::GzipCompressionProto(bytes) => bytes.len(), + CacheEntry::Lz4CompressionProto(bytes) => bytes.len(), CacheEntry::Base64UncompressedProto(bytes) => bytes.len(), } } @@ -103,13 +103,15 @@ impl CacheEntry { .encode(&mut bytes) .expect("proto serialization failed."); match storage_format { - StorageFormat::GzipCompressedProto => { - let mut compressed = GzEncoder::new(bytes.as_slice(), flate2::Compression::fast()); - let mut result = Vec::new(); + StorageFormat::Lz4CompressedProto => { + let mut compressed = EncoderBuilder::new() + .level(4) + .build(Vec::new()) + .expect("Lz4 compression failed."); compressed - .read_to_end(&mut result) - .expect("Gzip compression failed."); - CacheEntry::GzipCompressionProto(result) + .write_all(&bytes) + .expect("Lz4 compression failed."); + CacheEntry::Lz4CompressionProto(compressed.finish().0) }, StorageFormat::Base64UncompressedProto => { let base64 = base64::encode(bytes).into_bytes(); @@ -124,8 +126,8 @@ impl CacheEntry { pub fn build_key(version: u64, storage_format: StorageFormat) -> String { match storage_format { - StorageFormat::GzipCompressedProto => { - format!("gz:{}", version) + StorageFormat::Lz4CompressedProto => { + format!("l4:{}", version) }, StorageFormat::Base64UncompressedProto => { format!("{}", version) @@ -139,12 +141,12 @@ impl CacheEntry { pub fn into_transaction(self) -> Transaction { match self { - CacheEntry::GzipCompressionProto(bytes) => { - let mut decompressor = GzDecoder::new(&bytes[..]); + CacheEntry::Lz4CompressionProto(bytes) => { + let mut decompressor = Decoder::new(&bytes[..]).expect("Lz4 decompression failed."); let mut decompressed = Vec::new(); decompressor .read_to_end(&mut decompressed) - .expect("Gzip decompression failed."); + .expect("Lz4 decompression failed."); Transaction::decode(decompressed.as_slice()).expect("proto deserialization failed.") }, CacheEntry::Base64UncompressedProto(bytes) => { @@ -156,7 +158,7 @@ impl CacheEntry { } pub enum FileEntry { - GzipCompressionProto(Vec), + Lz4CompressionProto(Vec), // Only used for legacy file format. JsonBase64UncompressedProto(Vec), } @@ -164,7 +166,7 @@ pub enum FileEntry { impl FileEntry { pub fn new(bytes: Vec, storage_format: StorageFormat) -> Self { match storage_format { - StorageFormat::GzipCompressedProto => Self::GzipCompressionProto(bytes), + StorageFormat::Lz4CompressedProto => Self::Lz4CompressionProto(bytes), StorageFormat::Base64UncompressedProto => { panic!("Base64UncompressedProto is not supported.") }, @@ -174,14 +176,14 @@ impl FileEntry { pub fn into_inner(self) -> Vec { match self { - FileEntry::GzipCompressionProto(bytes) => bytes, + FileEntry::Lz4CompressionProto(bytes) => bytes, FileEntry::JsonBase64UncompressedProto(bytes) => bytes, } } pub fn size(&self) -> usize { match self { - FileEntry::GzipCompressionProto(bytes) => bytes.len(), + FileEntry::Lz4CompressionProto(bytes) => bytes.len(), FileEntry::JsonBase64UncompressedProto(bytes) => bytes.len(), } } @@ -203,18 +205,20 @@ impl FileEntry { panic!("Starting version has to be a multiple of FILE_ENTRY_TRANSACTION_COUNT.") } match storage_format { - StorageFormat::GzipCompressedProto => { + StorageFormat::Lz4CompressedProto => { let t = TransactionsInStorage { starting_version: Some(transactions.first().unwrap().version), transactions, }; t.encode(&mut bytes).expect("proto serialization failed."); - let mut compressed = GzEncoder::new(bytes.as_slice(), flate2::Compression::fast()); - let mut result = Vec::new(); + let mut compressed = EncoderBuilder::new() + .level(4) + .build(Vec::new()) + .expect("Lz4 compression failed."); compressed - .read_to_end(&mut result) - .expect("Gzip compression failed."); - FileEntry::GzipCompressionProto(result) + .write_all(&bytes) + .expect("Lz4 compression failed."); + FileEntry::Lz4CompressionProto(compressed.finish().0) }, StorageFormat::Base64UncompressedProto => { panic!("Base64UncompressedProto is not supported.") @@ -247,9 +251,9 @@ impl FileEntry { hasher.update(starting_version.to_string()); let file_prefix = format!("{:x}", hasher.finalize()); match storage_format { - StorageFormat::GzipCompressedProto => { + StorageFormat::Lz4CompressedProto => { format!( - "compressed_files/gzip/{}_{}.bin", + "compressed_files/lz4/{}_{}.bin", file_prefix, starting_version ) }, @@ -264,12 +268,12 @@ impl FileEntry { pub fn into_transactions_in_storage(self) -> TransactionsInStorage { match self { - FileEntry::GzipCompressionProto(bytes) => { - let mut decompressor = GzDecoder::new(&bytes[..]); + FileEntry::Lz4CompressionProto(bytes) => { + let mut decompressor = Decoder::new(&bytes[..]).expect("Lz4 decompression failed."); let mut decompressed = Vec::new(); decompressor .read_to_end(&mut decompressed) - .expect("Gzip decompression failed."); + .expect("Lz4 decompression failed."); TransactionsInStorage::decode(decompressed.as_slice()) .expect("proto deserialization failed.") }, @@ -317,7 +321,7 @@ mod tests { } #[test] - fn test_cache_entry_builder_gzip_compressed_proto() { + fn test_cache_entry_builder_lz4_compressed_proto() { let transaction = Transaction { version: 42, epoch: 333, @@ -326,7 +330,7 @@ mod tests { let transaction_clone = transaction.clone(); let proto_size = transaction.encoded_len(); let cache_entry = - CacheEntry::from_transaction(transaction, StorageFormat::GzipCompressedProto); + CacheEntry::from_transaction(transaction, StorageFormat::Lz4CompressedProto); let compressed_size = cache_entry.size(); assert!(compressed_size != proto_size); let deserialized_transaction = cache_entry.into_transaction(); @@ -379,7 +383,7 @@ mod tests { } #[test] - fn test_file_entry_builder_gzip_compressed_proto() { + fn test_file_entry_builder_lz4_compressed_proto() { let transactions = (1000..2000) .map(|version| Transaction { version, @@ -393,7 +397,7 @@ mod tests { }; let transactions_in_storage_size = transactions_in_storage.encoded_len(); let file_entry = - FileEntry::from_transactions(transactions.clone(), StorageFormat::GzipCompressedProto); + FileEntry::from_transactions(transactions.clone(), StorageFormat::Lz4CompressedProto); assert_ne!(file_entry.size(), transactions_in_storage_size); let deserialized_transactions = file_entry.into_transactions_in_storage(); for (i, transaction) in transactions.iter().enumerate() { @@ -402,10 +406,10 @@ mod tests { } #[test] - fn test_cache_entry_key_to_string_gzip_compressed_proto() { + fn test_cache_entry_key_to_string_lz4_compressed_proto() { assert_eq!( - CacheEntry::build_key(42, StorageFormat::GzipCompressedProto), - "gz:42" + CacheEntry::build_key(42, StorageFormat::Lz4CompressedProto), + "l4:42" ); } @@ -424,10 +428,10 @@ mod tests { } #[test] - fn test_file_entry_key_to_string_gzip_compressed_proto() { + fn test_file_entry_key_to_string_lz4_compressed_proto() { assert_eq!( - FileEntry::build_key(42, StorageFormat::GzipCompressedProto), - "compressed_files/gzip/3d1bff1ba654ca5fdb6ac1370533d876_0.bin" + FileEntry::build_key(42, StorageFormat::Lz4CompressedProto), + "compressed_files/lz4/3d1bff1ba654ca5fdb6ac1370533d876_0.bin" ); } @@ -470,7 +474,7 @@ mod tests { "chain_id": 1, "file_folder_size": 1000, "version": 1, - "storage_format": "GzipCompressedProto" + "storage_format": "Lz4CompressedProto" }"#; let file_metadata: FileStoreMetadata = serde_json::from_str(file_metadata_serialized_json) @@ -478,7 +482,7 @@ mod tests { assert_eq!( file_metadata.storage_format, - StorageFormat::GzipCompressedProto + StorageFormat::Lz4CompressedProto ); assert_eq!(file_metadata.chain_id, 1); assert_eq!(file_metadata.file_folder_size, 1000); diff --git a/ecosystem/indexer-grpc/indexer-grpc-utils/src/file_store_operator/gcs.rs b/ecosystem/indexer-grpc/indexer-grpc-utils/src/file_store_operator/gcs.rs index 05578bccdf898..444791cc23c63 100644 --- a/ecosystem/indexer-grpc/indexer-grpc-utils/src/file_store_operator/gcs.rs +++ b/ecosystem/indexer-grpc/indexer-grpc-utils/src/file_store_operator/gcs.rs @@ -31,7 +31,7 @@ impl GcsFileStoreOperator { ) -> Self { env::set_var(SERVICE_ACCOUNT_ENV_VAR, service_account_path); let storage_format = if enable_compression { - StorageFormat::GzipCompressedProto + StorageFormat::Lz4CompressedProto } else { StorageFormat::JsonBase64UncompressedProto }; diff --git a/ecosystem/indexer-grpc/indexer-grpc-utils/src/file_store_operator/local.rs b/ecosystem/indexer-grpc/indexer-grpc-utils/src/file_store_operator/local.rs index 65245733935a9..ada1740511fd5 100644 --- a/ecosystem/indexer-grpc/indexer-grpc-utils/src/file_store_operator/local.rs +++ b/ecosystem/indexer-grpc/indexer-grpc-utils/src/file_store_operator/local.rs @@ -23,7 +23,7 @@ pub struct LocalFileStoreOperator { impl LocalFileStoreOperator { pub fn new(path: PathBuf, enable_compression: bool) -> Self { let storage_format = if enable_compression { - StorageFormat::GzipCompressedProto + StorageFormat::Lz4CompressedProto } else { StorageFormat::JsonBase64UncompressedProto }; From e7e562c35c0111ab11190514a85da4aeb3c53ad1 Mon Sep 17 00:00:00 2001 From: larry-aptos <112209412+larry-aptos@users.noreply.github.com> Date: Tue, 9 Apr 2024 12:48:00 -0700 Subject: [PATCH 28/36] [indexer grpc] in-memory cache benchmarks. (#12711) --- ...ndexer-grpc-in-memory-cache-benchmark.yaml | 22 +++ Cargo.lock | 18 +- Cargo.toml | 2 + docker/builder/build-indexer.sh | 2 + docker/builder/indexer-grpc.Dockerfile | 1 + .../Cargo.toml | 25 +++ .../src/main.rs | 161 ++++++++++++++++++ .../indexer-grpc-utils/src/in_memory_cache.rs | 4 +- 8 files changed, 232 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/indexer-grpc-in-memory-cache-benchmark.yaml create mode 100644 ecosystem/indexer-grpc/indexer-grpc-in-memory-cache-benchmark/Cargo.toml create mode 100644 ecosystem/indexer-grpc/indexer-grpc-in-memory-cache-benchmark/src/main.rs diff --git a/.github/workflows/indexer-grpc-in-memory-cache-benchmark.yaml b/.github/workflows/indexer-grpc-in-memory-cache-benchmark.yaml new file mode 100644 index 0000000000000..c3548c30b085c --- /dev/null +++ b/.github/workflows/indexer-grpc-in-memory-cache-benchmark.yaml @@ -0,0 +1,22 @@ +name: Indexer gRPC in-memory cache benchmark +on: + workflow_dispatch: + schedule: + - cron: "0 0 * * *" + +jobs: + run-indexer-grpc-in-memory-cache-benchmark: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Install grpcurl + run: curl -sSL "https://github.com/fullstorydev/grpcurl/releases/download/v1.8.7/grpcurl_1.8.7_linux_x86_64.tar.gz" | sudo tar -xz -C /usr/local/bin + - name: Rust setup + uses: aptos-labs/aptos-core/.github/actions/rust-setup@main + with: + GIT_CREDENTIALS: ${{ secrets.GIT_CREDENTIALS }} + - name: build and run the benchmark + run: | + set -ex + cargo build --release --bin aptos-indexer-grpc-in-memory-cache-benchmark + ./target/release/indexer-grpc-in-memory-cache-benchmark \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 46cab3b23468b..722e3dd896b90 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2077,6 +2077,22 @@ dependencies = [ "tonic-reflection", ] +[[package]] +name = "aptos-indexer-grpc-in-memory-cache-benchmark" +version = "0.0.0" +dependencies = [ + "anyhow", + "aptos-indexer-grpc-utils", + "aptos-protos 1.3.0", + "futures", + "jemallocator", + "lazy_static", + "once_cell", + "redis", + "redis-test", + "tokio", +] + [[package]] name = "aptos-indexer-grpc-integration-tests" version = "0.1.0" @@ -8777,7 +8793,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.10", + "socket2 0.5.5", "tokio", "tower-service", "tracing", diff --git a/Cargo.toml b/Cargo.toml index bf4283068415e..79830ab816685 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -117,6 +117,7 @@ members = [ "ecosystem/indexer-grpc/indexer-grpc-data-service", "ecosystem/indexer-grpc/indexer-grpc-file-store", "ecosystem/indexer-grpc/indexer-grpc-fullnode", + "ecosystem/indexer-grpc/indexer-grpc-in-memory-cache-benchmark", "ecosystem/indexer-grpc/indexer-grpc-integration-tests", "ecosystem/indexer-grpc/indexer-grpc-server-framework", "ecosystem/indexer-grpc/indexer-grpc-table-info", @@ -345,6 +346,7 @@ aptos-indexer-grpc-data-service = { path = "ecosystem/indexer-grpc/indexer-grpc- aptos-indexer-grpc-data-access = { path = "ecosystem/indexer-grpc/indexer-grpc-data-access" } aptos-indexer-grpc-file-store = { path = "ecosystem/indexer-grpc/indexer-grpc-file-store" } aptos-indexer-grpc-fullnode = { path = "ecosystem/indexer-grpc/indexer-grpc-fullnode" } +aptos-indexer-grpc-in-memory-cache-benchmark = { path = "ecosystem/indexer-grpc/indexer-grpc-in-memory-cache-benchmark" } aptos-indexer-grpc-table-info = { path = "ecosystem/indexer-grpc/indexer-grpc-table-info" } aptos-indexer-grpc-utils = { path = "ecosystem/indexer-grpc/indexer-grpc-utils" } aptos-indexer-grpc-server-framework = { path = "ecosystem/indexer-grpc/indexer-grpc-server-framework" } diff --git a/docker/builder/build-indexer.sh b/docker/builder/build-indexer.sh index d7b91490f6fbc..9152cc6661210 100755 --- a/docker/builder/build-indexer.sh +++ b/docker/builder/build-indexer.sh @@ -16,6 +16,7 @@ cargo build --locked --profile=$PROFILE \ -p aptos-indexer-grpc-file-store \ -p aptos-indexer-grpc-data-service \ -p aptos-nft-metadata-crawler-parser \ + -p aptos-indexer-grpc-in-memory-cache-benchmark \ "$@" # After building, copy the binaries we need to `dist` since the `target` directory is used as docker cache mount and only available during the RUN step @@ -24,6 +25,7 @@ BINS=( aptos-indexer-grpc-file-store aptos-indexer-grpc-data-service aptos-nft-metadata-crawler-parser + aptos-indexer-grpc-in-memory-cache-benchmark ) mkdir dist diff --git a/docker/builder/indexer-grpc.Dockerfile b/docker/builder/indexer-grpc.Dockerfile index 22c0ab2eadb0e..ae6714ca6b9bd 100644 --- a/docker/builder/indexer-grpc.Dockerfile +++ b/docker/builder/indexer-grpc.Dockerfile @@ -17,6 +17,7 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ COPY --link --from=indexer-builder /aptos/dist/aptos-indexer-grpc-cache-worker /usr/local/bin/aptos-indexer-grpc-cache-worker COPY --link --from=indexer-builder /aptos/dist/aptos-indexer-grpc-file-store /usr/local/bin/aptos-indexer-grpc-file-store COPY --link --from=indexer-builder /aptos/dist/aptos-indexer-grpc-data-service /usr/local/bin/aptos-indexer-grpc-data-service +COPY --link --from=indexer-builder /aptos/dist/aptos-indexer-grpc-in-memory-cache-benchmark /usr/local/bin/aptos-indexer-grpc-in-memory-cache-benchmark # The health check port EXPOSE 8080 diff --git a/ecosystem/indexer-grpc/indexer-grpc-in-memory-cache-benchmark/Cargo.toml b/ecosystem/indexer-grpc/indexer-grpc-in-memory-cache-benchmark/Cargo.toml new file mode 100644 index 0000000000000..8cbfaee7e2e2e --- /dev/null +++ b/ecosystem/indexer-grpc/indexer-grpc-in-memory-cache-benchmark/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "aptos-indexer-grpc-in-memory-cache-benchmark" + +# Workspace inherited keys +authors = { workspace = true } +edition = { workspace = true } +homepage = { workspace = true } +license = { workspace = true } +publish = { workspace = true } +repository = { workspace = true } +rust-version = { workspace = true } + +[dependencies] +anyhow = { workspace = true } +aptos-indexer-grpc-utils = { workspace = true } +aptos-protos = { workspace = true } +futures = { workspace = true } +lazy_static = { workspace = true } +once_cell = { workspace = true } +redis = { workspace = true } +redis-test = { workspace = true } +tokio = { workspace = true } + +[target.'cfg(unix)'.dependencies] +jemallocator = { workspace = true } diff --git a/ecosystem/indexer-grpc/indexer-grpc-in-memory-cache-benchmark/src/main.rs b/ecosystem/indexer-grpc/indexer-grpc-in-memory-cache-benchmark/src/main.rs new file mode 100644 index 0000000000000..d5efe9f0e5835 --- /dev/null +++ b/ecosystem/indexer-grpc/indexer-grpc-in-memory-cache-benchmark/src/main.rs @@ -0,0 +1,161 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +// This benchmark is used to test the performance of in-memory cache. +// Key performance requirements: +// read speed +// * 20k reads per second for small load - 2 KB per txn for 10 clients. - TPS, ~4 Gbps. +// * 100 reads per second for large load - 1 MB per txn for 10 clients - memory-(de)allocation, ~10 Gbps. +// * 100 reads per second for small load - 2 KB per txn for 1000 clients - contended reads, ~2 Gbps. + +use aptos_indexer_grpc_utils::{ + compression_util::{CacheEntry, StorageFormat}, + in_memory_cache::{InMemoryCache, MAX_REDIS_FETCH_BATCH_SIZE}, +}; +use aptos_protos::transaction::v1::{Transaction, TransactionInfo}; +use lazy_static::lazy_static; +use once_cell::sync::OnceCell; +use redis_test::{MockCmd, MockRedisConnection}; +use std::sync::Arc; + +#[cfg(unix)] +#[global_allocator] +static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; + +lazy_static! { + static ref TRANSACTION_CONTENT: OnceCell> = OnceCell::new(); +} +// Create a transaction with a given version and size. +// This involves memory allocation. +fn generate_transaction_bytes(version: u64, size: usize) -> Vec { + let txn = Transaction { + version, + info: Some(TransactionInfo { + hash: TRANSACTION_CONTENT.get_or_init(|| vec![1; size]).clone(), + ..TransactionInfo::default() + }), + ..Transaction::default() + }; + let storage_format = StorageFormat::Lz4CompressedProto; + let cache_entry = CacheEntry::from_transaction(txn, storage_format); + cache_entry.into_inner() +} + +fn mock_get_latest_version(version: i64) -> MockCmd { + MockCmd::new(redis::cmd("GET").arg("latest_version"), Ok(version)) +} + +fn mock_mget_transactions(starting_version: u64, count: usize, txn_size: usize) -> MockCmd { + let keys: Vec = (0..count) + .map(|i| { + let version = starting_version + i as u64; + CacheEntry::build_key(version, StorageFormat::Lz4CompressedProto) + }) + .collect(); + let values = (0..count) + .map(|i| { + redis::Value::Data(generate_transaction_bytes( + starting_version + i as u64, + txn_size, + )) + }) + .collect(); + let redis_resp = redis::Value::Bulk(values); + MockCmd::new(redis::cmd("MGET").arg(keys), Ok(redis_resp)) +} + +fn generate_redis_commands(transaction_size: u64) -> Vec { + let mut redis_commands = vec![ + // No warm up. + mock_get_latest_version(0), + // Wait for a little bit since we're spawning up clients. + mock_get_latest_version(0), + mock_get_latest_version(0), + mock_get_latest_version(0), + mock_get_latest_version(0), + mock_get_latest_version(0), + ]; + + // number of batches. + let num_batches = 100 * 1024 * 1024 / (transaction_size as usize); + // Start to update. + for i in 0..num_batches { + redis_commands.push(mock_get_latest_version( + (i as i64 + 1) * MAX_REDIS_FETCH_BATCH_SIZE as i64, + )); + redis_commands.push(mock_mget_transactions( + i as u64 * (MAX_REDIS_FETCH_BATCH_SIZE as u64), + MAX_REDIS_FETCH_BATCH_SIZE, + transaction_size as usize, + )); + } + + redis_commands +} + +// Creates a mock Redis connection with a stream of commands. +// The pattern is: +// 1. Warm up: get latest_version, get transactions. +// 2. loop of fetching the data +fn create_mock_redis(transaction_size: u64) -> MockRedisConnection { + MockRedisConnection::new(generate_redis_commands(transaction_size)) +} + +// Spawn a task that consumes the cache. Return tps as a result. +fn spawn_cache_consumption_task( + cache: Arc, + duration_in_secs: u64, +) -> tokio::task::JoinHandle { + tokio::spawn(async move { + let start = std::time::Instant::now(); + let mut total_consumed_transactions = 0; + let mut current_version = 0; + while start.elapsed().as_secs() < duration_in_secs { + let txns = cache.get_transactions(current_version).await; + for txn in txns { + assert_eq!(txn.version, current_version); + total_consumed_transactions += 1; + current_version = txn.version + 1; + } + // Dropped here. + } + total_consumed_transactions as f64 / start.elapsed().as_secs_f64() + }) +} + +async fn run_transaction_test( + transaction_size: u64, + task_count: u64, + duration_in_secs: u64, + expected_tps: f64, +) { + let redis_connection = create_mock_redis(transaction_size); + let cache = Arc::new( + InMemoryCache::new_with_redis_connection( + redis_connection, + StorageFormat::Lz4CompressedProto, + ) + .await + .unwrap(), + ); + let tasks = (0..task_count) + .map(|_| spawn_cache_consumption_task(cache.clone(), duration_in_secs)) + .collect::>(); + // join all the tasks. + let tps = futures::future::join_all(tasks) + .await + .iter() + .map(|r| r.as_ref().unwrap()) + .sum::() + / task_count as f64; + println!("TPS: {}", tps); + assert!(tps > expected_tps); +} + +#[tokio::main(flavor = "multi_thread", worker_threads = 16)] +async fn main() -> anyhow::Result<()> { + run_transaction_test(2 * 1024, 10, 20, 20_000.0).await; + run_transaction_test(2 * 1024, 1000, 20, 100.0).await; + run_transaction_test(1024 * 1024, 20, 5, 500.0).await; + Ok(()) +} diff --git a/ecosystem/indexer-grpc/indexer-grpc-utils/src/in_memory_cache.rs b/ecosystem/indexer-grpc/indexer-grpc-utils/src/in_memory_cache.rs index 780d76eca8680..32d65d56cb67a 100644 --- a/ecosystem/indexer-grpc/indexer-grpc-utils/src/in_memory_cache.rs +++ b/ecosystem/indexer-grpc/indexer-grpc-utils/src/in_memory_cache.rs @@ -21,8 +21,8 @@ const IN_MEMORY_CACHE_EVICTION_TRIGGER_SIZE_IN_BYTES: u64 = 3_500_000_000; // Max cache entry TTL: 30 seconds. // const MAX_IN_MEMORY_CACHE_ENTRY_TTL: u64 = 30; // Warm-up cache entries. Pre-fetch the cache entries to warm up the cache. -const WARM_UP_CACHE_ENTRIES: u64 = 20_000; -const MAX_REDIS_FETCH_BATCH_SIZE: usize = 500; +pub const WARM_UP_CACHE_ENTRIES: u64 = 20_000; +pub const MAX_REDIS_FETCH_BATCH_SIZE: usize = 500; #[derive(Debug, Clone, Copy)] struct CacheMetadata { From df4772ccf46def1e03200707e360de60af7f504c Mon Sep 17 00:00:00 2001 From: Oliver He Date: Tue, 9 Apr 2024 18:30:43 -0400 Subject: [PATCH 29/36] Add print statements for keyless VK test (#12827) * add testnet vk script * Print out the hexlified vk in the print_groth16_pvk test * remove script --- types/src/keyless/bn254_circom.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/types/src/keyless/bn254_circom.rs b/types/src/keyless/bn254_circom.rs index 8de4f4cee513a..d65fbaf3c72d9 100644 --- a/types/src/keyless/bn254_circom.rs +++ b/types/src/keyless/bn254_circom.rs @@ -382,6 +382,15 @@ mod test { // representation of it. fn print_groth16_pvk() { let groth16_vk: Groth16VerificationKey = devnet_prepared_vk().into(); + + println!("alpha_g1: {:?}", hex::encode(groth16_vk.alpha_g1.clone())); + println!("beta_g2: {:?}", hex::encode(groth16_vk.beta_g2.clone())); + println!("gamma_g2: {:?}", hex::encode(groth16_vk.gamma_g2.clone())); + println!("delta_g2: {:?}", hex::encode(groth16_vk.delta_g2.clone())); + let gamma_abc_g1 = groth16_vk.gamma_abc_g1.clone(); + println!("gamma_abc_g1_0: {:?}", hex::encode(gamma_abc_g1[0].clone())); + println!("gamma_abc_g1_1: {:?}", hex::encode(gamma_abc_g1[1].clone())); + let same_pvk: PreparedVerifyingKey = groth16_vk.try_into().unwrap(); assert_eq!(same_pvk, devnet_prepared_vk()); From 08a45a7e8162feec86b7915b09d0b352ce4ab7cf Mon Sep 17 00:00:00 2001 From: Josh Lind Date: Mon, 8 Apr 2024 17:12:50 -0400 Subject: [PATCH 30/36] [Forge stable] Allow errors on failing forge tests. --- testsuite/forge-cli/src/main.rs | 175 +++++++++++++++++--------- testsuite/forge-cli/src/suites/dag.rs | 1 + 2 files changed, 120 insertions(+), 56 deletions(-) diff --git a/testsuite/forge-cli/src/main.rs b/testsuite/forge-cli/src/main.rs index bccb4797f078f..6650fd1988909 100644 --- a/testsuite/forge-cli/src/main.rs +++ b/testsuite/forge-cli/src/main.rs @@ -873,6 +873,7 @@ fn state_sync_failures_catching_up() -> ForgeConfig { 2500, true, false, + false, ChangingWorkingQuorumTest { min_tps: 1500, always_healthy_nodes: 2, @@ -885,73 +886,127 @@ fn state_sync_failures_catching_up() -> ForgeConfig { } fn state_sync_slow_processing_catching_up() -> ForgeConfig { - changing_working_quorum_test_helper(7, 300, 3000, 2500, true, true, ChangingWorkingQuorumTest { - min_tps: 750, - always_healthy_nodes: 2, - max_down_nodes: 0, - num_large_validators: 2, - add_execution_delay: true, - check_period_s: 57, - }) + changing_working_quorum_test_helper( + 7, + 300, + 3000, + 2500, + true, + true, + false, + ChangingWorkingQuorumTest { + min_tps: 750, + always_healthy_nodes: 2, + max_down_nodes: 0, + num_large_validators: 2, + add_execution_delay: true, + check_period_s: 57, + }, + ) } fn different_node_speed_and_reliability_test() -> ForgeConfig { - changing_working_quorum_test_helper(20, 120, 70, 50, true, false, ChangingWorkingQuorumTest { - min_tps: 30, - always_healthy_nodes: 6, - max_down_nodes: 5, - num_large_validators: 3, - add_execution_delay: true, - check_period_s: 27, - }) + changing_working_quorum_test_helper( + 20, + 120, + 70, + 50, + true, + false, + false, + ChangingWorkingQuorumTest { + min_tps: 30, + always_healthy_nodes: 6, + max_down_nodes: 5, + num_large_validators: 3, + add_execution_delay: true, + check_period_s: 27, + }, + ) } fn large_test_only_few_nodes_down() -> ForgeConfig { - changing_working_quorum_test_helper(60, 120, 100, 70, false, false, ChangingWorkingQuorumTest { - min_tps: 50, - always_healthy_nodes: 40, - max_down_nodes: 10, - num_large_validators: 0, - add_execution_delay: false, - check_period_s: 27, - }) + changing_working_quorum_test_helper( + 60, + 120, + 100, + 70, + false, + false, + false, + ChangingWorkingQuorumTest { + min_tps: 50, + always_healthy_nodes: 40, + max_down_nodes: 10, + num_large_validators: 0, + add_execution_delay: false, + check_period_s: 27, + }, + ) } fn changing_working_quorum_test_high_load() -> ForgeConfig { - changing_working_quorum_test_helper(16, 120, 500, 300, true, true, ChangingWorkingQuorumTest { - min_tps: 50, - always_healthy_nodes: 0, - max_down_nodes: 16, - num_large_validators: 0, - add_execution_delay: false, - // Use longer check duration, as we are bringing enough nodes - // to require state-sync to catch up to have consensus. - check_period_s: 53, - }) + changing_working_quorum_test_helper( + 16, + 120, + 500, + 300, + true, + true, + true, + ChangingWorkingQuorumTest { + min_tps: 50, + always_healthy_nodes: 0, + max_down_nodes: 16, + num_large_validators: 0, + add_execution_delay: false, + // Use longer check duration, as we are bringing enough nodes + // to require state-sync to catch up to have consensus. + check_period_s: 53, + }, + ) } fn changing_working_quorum_test() -> ForgeConfig { - changing_working_quorum_test_helper(16, 120, 100, 70, true, true, ChangingWorkingQuorumTest { - min_tps: 15, - always_healthy_nodes: 0, - max_down_nodes: 16, - num_large_validators: 0, - add_execution_delay: false, - // Use longer check duration, as we are bringing enough nodes - // to require state-sync to catch up to have consensus. - check_period_s: 53, - }) + changing_working_quorum_test_helper( + 16, + 120, + 100, + 70, + true, + true, + true, + ChangingWorkingQuorumTest { + min_tps: 15, + always_healthy_nodes: 0, + max_down_nodes: 16, + num_large_validators: 0, + add_execution_delay: false, + // Use longer check duration, as we are bringing enough nodes + // to require state-sync to catch up to have consensus. + check_period_s: 53, + }, + ) } fn consensus_stress_test() -> ForgeConfig { - changing_working_quorum_test_helper(10, 60, 100, 80, true, false, ChangingWorkingQuorumTest { - min_tps: 50, - always_healthy_nodes: 10, - max_down_nodes: 0, - num_large_validators: 0, - add_execution_delay: false, - check_period_s: 27, - }) + changing_working_quorum_test_helper( + 10, + 60, + 100, + 80, + true, + false, + false, + ChangingWorkingQuorumTest { + min_tps: 50, + always_healthy_nodes: 10, + max_down_nodes: 0, + num_large_validators: 0, + add_execution_delay: false, + check_period_s: 27, + }, + ) } fn realistic_env_sweep_wrap( @@ -2162,6 +2217,7 @@ pub fn changing_working_quorum_test_helper( min_avg_tps: usize, apply_txn_outputs: bool, use_chain_backoff: bool, + allow_errors: bool, test: ChangingWorkingQuorumTest, ) -> ForgeConfig { let config = ForgeConfig::default(); @@ -2237,8 +2293,8 @@ pub fn changing_working_quorum_test_helper( ), ]), ) - .with_success_criteria( - SuccessCriteria::new(min_avg_tps) + .with_success_criteria({ + let success_criteria = SuccessCriteria::new(min_avg_tps) .add_no_restarts() .add_wait_for_catchup_s(30) .add_chain_progress(StateProgressThreshold { @@ -2256,8 +2312,15 @@ pub fn changing_working_quorum_test_helper( 40.0 }, max_round_gap: 60, - }), - ) + }); + + // If errors are allowed, overwrite the success criteria + if allow_errors { + success_criteria.allow_errors() + } else { + success_criteria + } + }) } fn large_db_test( diff --git a/testsuite/forge-cli/src/suites/dag.rs b/testsuite/forge-cli/src/suites/dag.rs index 3a47518d8f434..90252cf7f7709 100644 --- a/testsuite/forge-cli/src/suites/dag.rs +++ b/testsuite/forge-cli/src/suites/dag.rs @@ -150,6 +150,7 @@ fn dag_changing_working_quorum_test() -> ForgeConfig { 70, true, true, + false, ChangingWorkingQuorumTest { min_tps: 15, always_healthy_nodes: 0, From 5fe2fdbfb3826aa9e7dd869df08e3169514f3ae3 Mon Sep 17 00:00:00 2001 From: Josh Lind Date: Wed, 3 Apr 2024 20:34:09 -0400 Subject: [PATCH 31/36] [CI/CD] Add targeted unit test job and delay all unit tests. --- .../rust-targeted-unit-tests/action.yaml | 49 +++++ .github/actions/rust-unit-tests/action.yaml | 3 +- .github/workflows/lint-test.yaml | 21 +++ devtools/aptos-cargo-cli/src/cargo.rs | 31 +++- devtools/aptos-cargo-cli/src/common.rs | 113 ++++++++++-- devtools/aptos-cargo-cli/src/lib.rs | 173 +++++++++++++++--- 6 files changed, 348 insertions(+), 42 deletions(-) create mode 100644 .github/actions/rust-targeted-unit-tests/action.yaml diff --git a/.github/actions/rust-targeted-unit-tests/action.yaml b/.github/actions/rust-targeted-unit-tests/action.yaml new file mode 100644 index 0000000000000..aaadf0cea9d05 --- /dev/null +++ b/.github/actions/rust-targeted-unit-tests/action.yaml @@ -0,0 +1,49 @@ +name: Rust Targeted Unit Tests +description: Runs only the targeted rust unit tests +inputs: + GIT_CREDENTIALS: + description: "Optional credentials to pass to git. Useful if you need to pull private repos for dependencies" + required: false + +runs: + using: composite + steps: + # The source code must be checked out by the workflow that invokes this action. + - uses: aptos-labs/aptos-core/.github/actions/rust-setup@main + with: + GIT_CREDENTIALS: ${{ inputs.GIT_CREDENTIALS }} + + # Install nextest + - uses: taiki-e/install-action@v1.5.6 + with: + tool: nextest + + # Run a postgres database + - name: Run postgres database + run: docker run --detach -p 5432:5432 cimg/postgres:14.2 + shell: bash + + # Output the changed files + - name: Output the changed files + run: cargo x changed-files -vv + shell: bash + + # Output the affected packages + - name: Output the affected packages + run: cargo x affected-packages -vv + shell: bash + + # Run only the targeted rust unit tests + - name: Run only the targeted unit tests + run: | + cargo x targeted-unit-tests -vv run --profile ci --cargo-profile ci --locked --no-fail-fast --retries 3 + shell: bash + env: + INDEXER_DATABASE_URL: postgresql://postgres@localhost/postgres + RUST_MIN_STACK: "4297152" + MVP_TEST_ON_CI: "true" + SOLC_EXE: /home/runner/bin/solc + Z3_EXE: /home/runner/bin/z3 + CVC5_EXE: /home/runner/bin/cvc5 + DOTNET_ROOT: /home/runner/.dotnet + BOOGIE_EXE: /home/runner/.dotnet/tools/boogie diff --git a/.github/actions/rust-unit-tests/action.yaml b/.github/actions/rust-unit-tests/action.yaml index f68562c6fbeb5..a0fb2c8103f1f 100644 --- a/.github/actions/rust-unit-tests/action.yaml +++ b/.github/actions/rust-unit-tests/action.yaml @@ -12,7 +12,6 @@ runs: using: composite steps: # The source code must be checkout out by the workflow that invokes this action. - - uses: aptos-labs/aptos-core/.github/actions/rust-setup@main with: GIT_CREDENTIALS: ${{ inputs.GIT_CREDENTIALS }} @@ -31,7 +30,7 @@ runs: - uses: taiki-e/install-action@v1.5.6 with: tool: nextest - + # Install buildkite-test-collector - name: Install buildkite-test-collector run: cargo install buildkite-test-collector diff --git a/.github/workflows/lint-test.yaml b/.github/workflows/lint-test.yaml index a73373049c76d..6492090ad45d6 100644 --- a/.github/workflows/lint-test.yaml +++ b/.github/workflows/lint-test.yaml @@ -106,9 +106,30 @@ jobs: - run: echo "Skipping rust smoke tests! Unrelated changes detected." if: needs.file_change_determinator.outputs.only_docs_changed == 'true' + # Run only the targeted rust unit tests. This is a PR required job. + rust-targeted-unit-tests: + needs: file_change_determinator + runs-on: high-perf-docker + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 # Fetch all git history for accurate target determination + - name: Run targeted rust unit tests + uses: ./.github/actions/rust-targeted-unit-tests + with: + GIT_CREDENTIALS: ${{ secrets.GIT_CREDENTIALS }} + # Run all rust unit tests. This is a PR required job. rust-unit-tests: needs: file_change_determinator + if: | # Only run on each PR once an appropriate event occurs + ( + github.event_name == 'workflow_dispatch' || + github.event_name == 'push' || + contains(github.event.pull_request.labels.*.name, 'CICD:run-all-unit-tests') || + github.event.pull_request.auto_merge != null + ) runs-on: high-perf-docker steps: - uses: actions/checkout@v4 diff --git a/devtools/aptos-cargo-cli/src/cargo.rs b/devtools/aptos-cargo-cli/src/cargo.rs index 5d7731adefa0d..c3fbcbcc388df 100644 --- a/devtools/aptos-cargo-cli/src/cargo.rs +++ b/devtools/aptos-cargo-cli/src/cargo.rs @@ -1,12 +1,13 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use log::debug; +use log::info; use std::{ ffi::{OsStr, OsString}, process::{Command, Stdio}, }; +#[derive(Debug)] pub struct Cargo { inner: Command, pass_through_args: Vec, @@ -46,14 +47,36 @@ impl Cargo { } pub fn run(&mut self) { + // Set up the output and arguments self.inner.stdout(Stdio::inherit()).stderr(Stdio::inherit()); - if !self.pass_through_args.is_empty() { self.inner.arg("--").args(&self.pass_through_args); } - debug!("Executing command: {:?}", self.inner); + // Log the command + let command_to_execute = format!("{:?}", self.inner); + info!("Executing command: {:?}", command_to_execute); + + // Execute the command + let result = self.inner.output(); - let _ = self.inner.output(); + // If the command failed, panic immediately with the error. + // This will ensure that failures are not dropped silently. + match result { + Ok(output) => { + if !output.status.success() { + panic!( + "Command failed: {:?}. Output: {:?}", + command_to_execute, output + ); + } + }, + Err(error) => { + panic!( + "Unexpected error executing command: {:?}. Error: {:?}", + command_to_execute, error + ); + }, + } } } diff --git a/devtools/aptos-cargo-cli/src/common.rs b/devtools/aptos-cargo-cli/src/common.rs index 4b2b76bd51514..e2411a8c6fbef 100644 --- a/devtools/aptos-cargo-cli/src/common.rs +++ b/devtools/aptos-cargo-cli/src/common.rs @@ -3,8 +3,18 @@ use anyhow::anyhow; use clap::Args; -use determinator::{Determinator, Utf8Paths0}; -use guppy::{graph::DependencyDirection, CargoMetadata, MetadataCommand}; +use determinator::{ + rules::{DeterminatorMarkChanged, DeterminatorPostRule, DeterminatorRules, PathRule}, + Determinator, Utf8Paths0, +}; +use guppy::{ + graph::{ + cargo::{CargoOptions, CargoResolverVersion}, + DependencyDirection, PackageGraph, + }, + CargoMetadata, MetadataCommand, +}; +use log::{debug, info}; use std::{ fs, io::Read, @@ -13,6 +23,23 @@ use std::{ }; use url::Url; +// File types in `aptos-core` that are not relevant to the rust build and test process. +// Note: this is a best effort list and will need to be updated as time goes on. +const IGNORED_DETERMINATOR_FILE_TYPES: [&str; 4] = ["*.json", "*.md", "*.yaml", "*.yml"]; + +// Paths in `aptos-core` that are not relevant to the rust build and test process. +// Note: this is a best effort list and will need to be updated as time goes on. +const IGNORED_DETERMINATOR_PATHS: [&str; 8] = [ + ".assets/*", + ".github/*", + ".vscode/*", + "dashboards/*", + "developer-docs-site/*", + "docker/*", + "scripts/*", + "terraform/*", +]; + fn workspace_dir() -> PathBuf { let output = Command::new("cargo") .arg("locate-project") @@ -92,17 +119,17 @@ impl SelectedPackageArgs { Ok(CargoMetadata::parse_json(&contents)?) } - pub fn compute_packages(&self) -> anyhow::Result> { - if !self.package.is_empty() { - return Ok(self.package.clone()); - } - - // Determine merge base - // TODO: support different merge bases - let merge_base = "origin/main"; + /// Identifies the changed files compared to the merge base, and + /// returns the relevant package graphs and file list. + pub fn identify_changed_files( + &self, + ) -> anyhow::Result<(PackageGraph, PackageGraph, Utf8Paths0)> { + // Determine the merge base + let merge_base = self.identify_merge_base(); + info!("Identified the merge base: {:?}", merge_base); // Download merge base metadata - let base_metadata = self.fetch_remote_metadata(merge_base)?; + let base_metadata = self.fetch_remote_metadata(&merge_base)?; let base_package_graph = base_metadata.build_graph().unwrap(); // Compute head metadata @@ -112,14 +139,72 @@ impl SelectedPackageArgs { let head_package_graph = head_metadata.build_graph().unwrap(); // Compute changed files - let changed_files = self.compute_changed_files(merge_base)?; + let changed_files = self.compute_changed_files(&merge_base)?; + debug!("Identified the changed files: {:?}", changed_files); + + // Return the package graphs and the changed files + Ok((base_package_graph, head_package_graph, changed_files)) + } + + /// Identifies the merge base to compare against. This is done by identifying + /// the commit at which the current branch forked off origin/main. + /// TODO: do we need to make this more intelligent? + fn identify_merge_base(&self) -> String { + // Run the git merge-base command + let output = Command::new("git") + .arg("merge-base") + .arg("HEAD") + .arg("origin/main") + .output() + .expect("failed to execute git merge-base"); + + // Return the output + String::from_utf8(output.stdout) + .expect("invalid UTF-8") + .trim() + .to_owned() + } + + /// Computes the affected target packages based on the + /// merge base and changed file set. + pub fn compute_target_packages(&self) -> anyhow::Result> { + if !self.package.is_empty() { + return Ok(self.package.clone()); + } + + // Compute changed files + let (base_package_graph, head_package_graph, changed_files) = + self.identify_changed_files()?; - // Run target determinator + // Create the determinator using the package graphs let mut determinator = Determinator::new(&base_package_graph, &head_package_graph); - // The determinator expects a list of changed files to be passed in. + + // Add the changed files to the determinator determinator.add_changed_paths(&changed_files); + // Set the cargo options for the determinator + let mut cargo_options = CargoOptions::new(); + cargo_options.set_resolver(CargoResolverVersion::V2); + determinator.set_cargo_options(&cargo_options); + + // Set the ignore rules for the determinator + let mut rules = DeterminatorRules::default(); + for globs in [ + IGNORED_DETERMINATOR_FILE_TYPES.to_vec(), + IGNORED_DETERMINATOR_PATHS.to_vec(), + ] { + rules.path_rules.push(PathRule { + globs: globs.iter().map(|string| string.to_string()).collect(), + mark_changed: DeterminatorMarkChanged::Packages(vec![]), + post_rule: DeterminatorPostRule::Skip, + }); + } + determinator.set_rules(&rules).unwrap(); + + // Run the target determinator let determinator_set = determinator.compute(); + + // Collect the affected packages let package_set = determinator_set .affected_set .packages(DependencyDirection::Forward) diff --git a/devtools/aptos-cargo-cli/src/lib.rs b/devtools/aptos-cargo-cli/src/lib.rs index 3b7aa2e9837ff..f77d425a78791 100644 --- a/devtools/aptos-cargo-cli/src/lib.rs +++ b/devtools/aptos-cargo-cli/src/lib.rs @@ -7,7 +7,11 @@ mod common; use cargo::Cargo; use clap::{Args, Parser, Subcommand}; pub use common::SelectedPackageArgs; -use log::trace; +use determinator::Utf8Paths0; +use log::{debug, trace}; + +// The targeted unit test packages to ignore (these will be run separately, by other jobs) +const TARGETED_TEST_PACKAGES_TO_IGNORE: [&str; 2] = ["aptos-testcases", "smoke-test"]; #[derive(Args, Clone, Debug)] #[command(disable_help_flag = true)] @@ -29,10 +33,13 @@ impl CommonArgs { #[derive(Clone, Subcommand, Debug)] pub enum AptosCargoCommand { + AffectedPackages(CommonArgs), + ChangedFiles(CommonArgs), Check(CommonArgs), Xclippy(CommonArgs), Fmt(CommonArgs), Nextest(CommonArgs), + TargetedUnitTests(CommonArgs), Test(CommonArgs), } @@ -43,16 +50,21 @@ impl AptosCargoCommand { AptosCargoCommand::Xclippy(_) => "clippy", AptosCargoCommand::Fmt(_) => "fmt", AptosCargoCommand::Nextest(_) => "nextest", + AptosCargoCommand::TargetedUnitTests(_) => "nextest", // Invoke the nextest command directly AptosCargoCommand::Test(_) => "test", + command => panic!("Unsupported command attempted! Command: {:?}", command), } } fn command_args(&self) -> &CommonArgs { match self { + AptosCargoCommand::AffectedPackages(args) => args, + AptosCargoCommand::ChangedFiles(args) => args, AptosCargoCommand::Check(args) => args, AptosCargoCommand::Xclippy(args) => args, AptosCargoCommand::Fmt(args) => args, AptosCargoCommand::Nextest(args) => args, + AptosCargoCommand::TargetedUnitTests(args) => args, AptosCargoCommand::Test(args) => args, } } @@ -71,42 +83,159 @@ impl AptosCargoCommand { } } - fn split_args(&self) -> (Vec, Vec) { - self.command_args().args() - } + fn get_args_and_affected_packages( + &self, + package_args: &SelectedPackageArgs, + ) -> anyhow::Result<(Vec, Vec, Vec)> { + // Parse the args + let (direct_args, push_through_args) = self.parse_args(); - pub fn execute(&self, package_args: &SelectedPackageArgs) -> anyhow::Result<()> { - let (mut direct_args, mut push_through_args) = self.split_args(); + // Compute the affected packages + let packages = package_args.compute_target_packages()?; + trace!("affected packages: {:?}", packages); - trace!("parsed direct_args: {:?}", direct_args); - trace!("parsed push_through_args: {:?}", push_through_args); + // Return the parsed args and packages + Ok((direct_args, push_through_args, packages)) + } - let packages = package_args.compute_packages()?; + fn parse_args(&self) -> (Vec, Vec) { + // Parse the args + let (direct_args, push_through_args) = self.command_args().args(); - trace!("affected packages: {:?}", packages); + // Trace log for debugging + trace!("parsed direct_arg`s: {:?}", direct_args); + trace!("parsed push_through_args: {:?}", push_through_args); - for p in packages { - direct_args.push("-p".into()); - direct_args.push(p); - } + (direct_args, push_through_args) + } - if let Some(opts) = self.extra_opts() { - for &opt in opts { - push_through_args.push(opt.into()); - } + pub fn execute(&self, package_args: &SelectedPackageArgs) -> anyhow::Result<()> { + match self { + AptosCargoCommand::AffectedPackages(_) => { + // Calculate and display the affected packages + let packages = package_args.compute_target_packages()?; + output_affected_packages(packages) + }, + AptosCargoCommand::ChangedFiles(_) => { + // Calculate and display the changed files + let (_, _, changed_files) = package_args.identify_changed_files()?; + output_changed_files(changed_files) + }, + AptosCargoCommand::TargetedUnitTests(_) => { + // Calculate and run the targeted unit tests. + // Start by fetching the arguments and affected packages. + let (mut direct_args, push_through_args, packages) = + self.get_args_and_affected_packages(package_args)?; + + // Add each affected package to the arguments, but filter out + // the packages that should not be run as unit tests. + let mut found_package_to_test = false; + for package_path in packages { + // Extract the package name from the full path + let package_name = package_path.split('#').last().unwrap(); + + // Only add the package if it is not in the ignore list + if TARGETED_TEST_PACKAGES_TO_IGNORE.contains(&package_name) { + debug!( + "Ignoring package when running targeted-unit-tests: {:?}", + package_name + ); + } else { + // Add the arguments for the package + direct_args.push("-p".into()); + direct_args.push(package_path); + + // Mark that we found a package to test + found_package_to_test = true; + } + } + + // Create and run the command if we found a package to test + if found_package_to_test { + println!("Running the targeted unit tests..."); + return self.create_and_run_command(direct_args, push_through_args); + } + + println!("Skipping targeted unit tests because no packages were affected to test."); + Ok(()) + }, + _ => { + // Otherwise, we need to parse and run the command. + // Start by fetching the arguments and affected packages. + let (mut direct_args, mut push_through_args, packages) = + self.get_args_and_affected_packages(package_args)?; + + // Add each affected package to the arguments + for package_path in packages { + direct_args.push("-p".into()); + direct_args.push(package_path); + } + + // Add any additional arguments + if let Some(opts) = self.extra_opts() { + for &opt in opts { + push_through_args.push(opt.into()); + } + } + + // Create and run the command + self.create_and_run_command(direct_args, push_through_args) + }, } + } + fn create_and_run_command( + &self, + direct_args: Vec, + push_through_args: Vec, + ) -> anyhow::Result<()> { + // Output the final arguments before running the command trace!("final direct_args: {:?}", direct_args); trace!("final push_through_args: {:?}", push_through_args); - Cargo::command(self.command()) - .args(direct_args) - .pass_through(push_through_args) - .run(); + // Construct and run the final command + let mut command = Cargo::command(self.command()); + command.args(direct_args).pass_through(push_through_args); + command.run(); + Ok(()) } } +/// Outputs the specified affected packages +fn output_affected_packages(packages: Vec) -> anyhow::Result<()> { + // Output the affected packages (if they exist) + if packages.is_empty() { + println!("No packages were affected!"); + } else { + println!("Affected packages detected:"); + for package in packages { + println!("\t{:?}", package) + } + } + Ok(()) +} + +/// Outputs the changed files from the given package args +fn output_changed_files(changed_files: Utf8Paths0) -> anyhow::Result<()> { + // Output the results + let mut changes_detected = false; + for (index, file) in changed_files.into_iter().enumerate() { + if index == 0 { + println!("Changed files detected:"); // Only print this if changes were detected! + changes_detected = true; + } + println!("\t{:?}", file) + } + + // If no changes were detected, make it obvious + if !changes_detected { + println!("No changes were detected!") + } + + Ok(()) +} + #[derive(Parser, Debug, Clone)] #[clap(author, version)] pub struct AptosCargoCli { From 3d4e63c51d50b6dd3d421663089153df5083747a Mon Sep 17 00:00:00 2001 From: Teng Zhang Date: Tue, 9 Apr 2024 16:58:05 -0700 Subject: [PATCH 32/36] fix function call ref (#12829) --- .../pipeline/reference_safety_processor.rs | 18 ++++++++++++++---- .../tests/reference-safety/function_ref.exp | 2 ++ .../tests/reference-safety/function_ref.move | 19 +++++++++++++++++++ .../reference-safety/function_ref.no-opt.exp | 2 ++ .../reference-safety/function_ref_err.exp | 13 +++++++++++++ .../reference-safety/function_ref_err.move | 19 +++++++++++++++++++ .../function_ref_err.no-opt.exp | 13 +++++++++++++ .../v1-tests/call_transfer_borrows.exp | 14 -------------- .../v1-tests/call_transfer_borrows.move | 2 +- .../v1-tests/call_transfer_borrows.no-opt.exp | 14 -------------- 10 files changed, 83 insertions(+), 33 deletions(-) create mode 100644 third_party/move/move-compiler-v2/tests/reference-safety/function_ref.exp create mode 100644 third_party/move/move-compiler-v2/tests/reference-safety/function_ref.move create mode 100644 third_party/move/move-compiler-v2/tests/reference-safety/function_ref.no-opt.exp create mode 100644 third_party/move/move-compiler-v2/tests/reference-safety/function_ref_err.exp create mode 100644 third_party/move/move-compiler-v2/tests/reference-safety/function_ref_err.move create mode 100644 third_party/move/move-compiler-v2/tests/reference-safety/function_ref_err.no-opt.exp diff --git a/third_party/move/move-compiler-v2/src/pipeline/reference_safety_processor.rs b/third_party/move/move-compiler-v2/src/pipeline/reference_safety_processor.rs index e1660ef2d2e01..8443012af1598 100644 --- a/third_party/move/move-compiler-v2/src/pipeline/reference_safety_processor.rs +++ b/third_party/move/move-compiler-v2/src/pipeline/reference_safety_processor.rs @@ -1486,9 +1486,12 @@ impl<'env, 'state> LifetimeAnalysisStep<'env, 'state> { ); } - /// Process a function call. For now we implement standard Move semantics, where every - /// output reference is a child of all input references. Here would be the point where to - // evaluate lifetime modifiers in future language versions. + /// Process a function call. For now we implement standard Move semantics, where + /// 1) every output immutable reference is a child of all input references; + /// 2) every output mutable reference is a child of all input mutable references, + /// because mutable references cannot be derived from immutable references. + /// Here would be the point where to + /// evaluate lifetime modifiers in future language versions. fn call_operation(&mut self, oper: Operation, dests: &[TempIndex], srcs: &[TempIndex]) { // Check validness of arguments for src in srcs { @@ -1498,7 +1501,9 @@ impl<'env, 'state> LifetimeAnalysisStep<'env, 'state> { for dest in dests { self.check_write_local(*dest) } - // Now draw edges from all reference sources to all reference destinations. + // Now draw edges + // 1) from all reference sources to all immutable reference destinations. + // 2) from all mutable reference sources to all mutable reference destinations. let dest_labels = dests .iter() .filter(|d| self.ty(**d).is_reference()) @@ -1515,6 +1520,11 @@ impl<'env, 'state> LifetimeAnalysisStep<'env, 'state> { for (i, src) in srcs.iter().enumerate() { let src_ty = self.ty(*src); if src_ty.is_reference() { + // dest does not rely on src if + // dest is a mutable reference while src is not + if dest_ty.is_mutable_reference() && !src_ty.is_mutable_reference() { + continue; + } let label = self.state.make_temp( *src, self.code_offset, diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/function_ref.exp b/third_party/move/move-compiler-v2/tests/reference-safety/function_ref.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/reference-safety/function_ref.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/function_ref.move b/third_party/move/move-compiler-v2/tests/reference-safety/function_ref.move new file mode 100644 index 0000000000000..9c1b9e2be6e41 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/reference-safety/function_ref.move @@ -0,0 +1,19 @@ +module 0x42::m { + public fun g(x: &mut u64, _y: &address): &mut u64 { + x + } + + public fun f(x: &u64, _y: &address): &u64 { + x + } + + public fun f1( + addr: address, + ){ + let h = 5; + let au = g(&mut 3, &addr); + let du = f(&h, &addr); + *du > 0; + *au > 1; + } +} diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/function_ref.no-opt.exp b/third_party/move/move-compiler-v2/tests/reference-safety/function_ref.no-opt.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/reference-safety/function_ref.no-opt.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/function_ref_err.exp b/third_party/move/move-compiler-v2/tests/reference-safety/function_ref_err.exp new file mode 100644 index 0000000000000..52f2b39e8e559 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/reference-safety/function_ref_err.exp @@ -0,0 +1,13 @@ + +Diagnostics: +error: cannot immutably borrow since mutable references exist + ┌─ tests/reference-safety/function_ref_err.move:15:18 + │ +14 │ let au = g_mut(&mut 3, &mut addr); + │ ------------------------ previous mutable call result +15 │ let du = f_mut(&h, &mut addr); + │ ^^^^^^^^^^^^^^^^^^^^ immutable borrow attempted here +16 │ *du > 0; + │ --- requirement enforced here +17 │ *au > 1; + │ --- conflicting reference `au` used here diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/function_ref_err.move b/third_party/move/move-compiler-v2/tests/reference-safety/function_ref_err.move new file mode 100644 index 0000000000000..0c9f9268660be --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/reference-safety/function_ref_err.move @@ -0,0 +1,19 @@ +module 0x42::m { + public fun g_mut(x: &mut u64, _y: &mut address): &mut u64 { + x + } + + public fun f_mut(x: &u64, _y: &mut address): &u64 { + x + } + + public fun f2( + addr: address, + ){ + let h = 5; + let au = g_mut(&mut 3, &mut addr); + let du = f_mut(&h, &mut addr); + *du > 0; + *au > 1; + } +} diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/function_ref_err.no-opt.exp b/third_party/move/move-compiler-v2/tests/reference-safety/function_ref_err.no-opt.exp new file mode 100644 index 0000000000000..52f2b39e8e559 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/reference-safety/function_ref_err.no-opt.exp @@ -0,0 +1,13 @@ + +Diagnostics: +error: cannot immutably borrow since mutable references exist + ┌─ tests/reference-safety/function_ref_err.move:15:18 + │ +14 │ let au = g_mut(&mut 3, &mut addr); + │ ------------------------ previous mutable call result +15 │ let du = f_mut(&h, &mut addr); + │ ^^^^^^^^^^^^^^^^^^^^ immutable borrow attempted here +16 │ *du > 0; + │ --- requirement enforced here +17 │ *au > 1; + │ --- conflicting reference `au` used here diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_transfer_borrows.exp b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_transfer_borrows.exp index 7ab29034dde81..e3106d41ea1a9 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_transfer_borrows.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_transfer_borrows.exp @@ -1,19 +1,5 @@ Diagnostics: -error: cannot move local `x` which is still borrowed - ┌─ tests/reference-safety/v1-tests/call_transfer_borrows.move:17:9 - │ -13 │ let x_ref = &x; - │ -- previous local borrow -14 │ let y_ref = &mut y; -15 │ let r = take_imm_mut_give_mut(x_ref, y_ref); - │ ----------------------------------- used by mutable call result -16 │ *x_ref; -17 │ move x; // error in v2 (bug in v1)? - │ ^^^^^^ moved here -18 │ *r = 1; - │ ------ conflicting reference `r` used here - error: mutable reference in local `y_ref` requires exclusive access but is borrowed ┌─ tests/reference-safety/v1-tests/call_transfer_borrows.move:29:9 │ diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_transfer_borrows.move b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_transfer_borrows.move index d16293b387d31..aef80bed497df 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_transfer_borrows.move +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_transfer_borrows.move @@ -14,7 +14,7 @@ module 0x8675309::M { let y_ref = &mut y; let r = take_imm_mut_give_mut(x_ref, y_ref); *x_ref; - move x; // error in v2 (bug in v1)? + move x; *r = 1; } diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_transfer_borrows.no-opt.exp b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_transfer_borrows.no-opt.exp index 7ab29034dde81..e3106d41ea1a9 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_transfer_borrows.no-opt.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_transfer_borrows.no-opt.exp @@ -1,19 +1,5 @@ Diagnostics: -error: cannot move local `x` which is still borrowed - ┌─ tests/reference-safety/v1-tests/call_transfer_borrows.move:17:9 - │ -13 │ let x_ref = &x; - │ -- previous local borrow -14 │ let y_ref = &mut y; -15 │ let r = take_imm_mut_give_mut(x_ref, y_ref); - │ ----------------------------------- used by mutable call result -16 │ *x_ref; -17 │ move x; // error in v2 (bug in v1)? - │ ^^^^^^ moved here -18 │ *r = 1; - │ ------ conflicting reference `r` used here - error: mutable reference in local `y_ref` requires exclusive access but is borrowed ┌─ tests/reference-safety/v1-tests/call_transfer_borrows.move:29:9 │ From d7c50d7d4928e510e23710784325fa94e3392c9e Mon Sep 17 00:00:00 2001 From: Vineeth Kashyap Date: Wed, 10 Apr 2024 12:12:46 -0400 Subject: [PATCH 33/36] [compiler-v2] Adding full compiler pipeline to many test configs (#12831) * Adding full compiler pass to no-simplifier tests * Adding full compiler pass for inline-et-al * Adding full compiler pipeline to "simplifier-full" * Adding full compiler pipeline to "ability-check". * Adding full compiler pipeline to "unreachable-code" tests * Removing turning off ability check from unreachable code. * Adding full compiler pipeline to "unit-test-on" tests. * Adding entire compiler pipeline to "unit-test-off". * Adding full compiler pipeline to "skip-attribute-checks". --- .../tests/ability-check/drop_on_abort.exp | 2 + .../tests/ability-check/resources.exp | 2 + .../tests/ability-check/unused_var.exp | 3 + .../checking/inlining/acquires_error_msg.exp | 3 + .../tests/checking/inlining/bug_11112.exp | 3 + .../tests/checking/inlining/bug_11223.exp | 3 + .../tests/checking/inlining/bug_9717.exp | 3 + .../checking/inlining/bug_9717_looponly.exp | 3 + .../tests/checking/inlining/deep_exp.exp | 3 + .../checking/inlining/double_nesting.exp | 3 + .../inlining/inline_accessing_constant.exp | 3 + .../tests/checking/inlining/lambda.exp | 3 + .../tests/checking/inlining/lambda_cast.exp | 3 + .../tests/checking/inlining/nested_mul.exp | 3 + .../checking/inlining/order_sensitive.exp | 3 + .../checking/inlining/recursive_nesting.exp | 3 + .../checking/inlining/resources_invalid.exp | 8 + .../checking/inlining/shadowing_unused.exp | 3 + .../inlining/shadowing_unused_nodecl.exp | 3 + .../tests/checking/inlining/spec_inlining.exp | 3 + .../checking/inlining/temp_shadowing.exp | 3 + .../tests/checking/inlining/test_12670.exp | 3 + .../tests/checking/inlining/unused_inline.exp | 3 + .../tests/folding/constant_values.exp | 3 + .../tests/folding/non_constant_empty_vec.exp | 3 + .../constant_folding_ristretto.exp | 3 + .../moved_var_not_simplified3.exp | 3 + .../always_false_branch.exp | 3 + .../simplifier-elimination/binary_add.exp | 3 + .../bind_with_type_annot.exp | 3 + .../constant_all_valid_types.exp | 3 + .../simplifier-elimination/double_nesting.exp | 3 + .../else_assigns_if_doesnt.exp | 8 + .../if_assigns_else_doesnt.exp | 8 + .../if_assigns_no_else.exp | 3 + .../simplifier-elimination/if_condition.exp | 3 + .../recursive_nesting.exp | 3 + .../use_before_assign.exp | 8 + .../use_before_assign_loop.exp | 32 ++++ .../use_before_assign_while.exp | 26 ++++ .../tests/simplifier/bug_11112.exp | 3 + .../tests/simplifier/conditional_borrow.exp | 3 + .../simplifier/constant_folding_ristretto.exp | 3 + .../tests/simplifier/deep_exp.exp | 3 + .../tests/simplifier/simplifier_test1.exp | 3 + .../tests/simplifier/simplifier_test2.exp | 3 + .../tests/simplifier/simplifier_test3.exp | 3 + .../aptos_stdlib_attributes2.exp | 2 + .../attribute_placement.exp | 2 + .../attribute_variants.exp | 2 + .../extra_attributes.exp | 2 + .../extra_attributes2.exp | 2 + .../tests/skip_attribute_checks/testonly.exp | 2 + .../move/move-compiler-v2/tests/testsuite.rs | 43 +++--- .../unit_test/notest/attribute_location.exp | 2 + .../unit_test/notest/cross_module_members.exp | 2 + .../notest/expected_failure_bad_value.exp | 2 + .../notest/expected_failure_constants.exp | 2 + .../expected_failure_constants_invalid.exp | 2 + .../expected_failure_invalid_literals.exp | 2 + .../notest/expected_failure_not_test.exp | 2 + .../expected_failure_out_of_range_value.exp | 2 + .../unit_test/notest/extra_attributes.exp | 2 + .../unit_test/notest/extra_attributes2.exp | 2 + .../notest/invalid_expected_code_name.exp | 2 + .../notest/invalid_expected_failure_name.exp | 2 + .../unit_test/notest/multiple_errors.exp | 2 + .../notest/multiple_test_annotations.exp | 2 + .../named_address_no_value_in_annotation.exp | 2 + .../other_failures_invalid_assignment.exp | 2 + .../other_failures_invalid_location.exp | 2 + ...other_failures_invalid_location_module.exp | 2 + .../unit_test/notest/other_failures_valid.exp | 2 + .../notest/test_and_test_only_annotation.exp | 2 + .../unit_test/notest/valid_test_module.exp | 2 + .../unit_test/test/attribute_location.exp | 2 + .../unit_test/test/cross_module_members.exp | 2 + ...cross_module_members_non_test_function.exp | 2 + .../test/cross_module_test_only_module.exp | 2 + .../test/expected_failure_bad_value.exp | 2 + .../test/expected_failure_constants.exp | 2 + .../expected_failure_constants_invalid.exp | 2 + .../expected_failure_invalid_literals.exp | 2 + .../test/expected_failure_not_test.exp | 2 + .../expected_failure_out_of_range_value.exp | 2 + .../tests/unit_test/test/extra_attributes.exp | 2 + .../test/invalid_expected_code_name.exp | 2 + .../test/invalid_expected_failure_name.exp | 2 + .../other_failures_invalid_assignment.exp | 2 + .../test/other_failures_invalid_location.exp | 2 + .../unit_test/test/other_failures_valid.exp | 2 + .../test/test_and_test_only_annotation.exp | 2 + .../unit_test/test/test_filter_function.exp | 2 + .../unit_test/test/test_filter_struct.exp | 2 + .../unit_test/test/valid_test_module.exp | 2 + .../unreachable-code-remover/abort_only.exp | 18 +-- .../abort_or_return_always.exp | 58 +------ .../always_false_branch.exp | 81 +--------- .../break_unreachable.exp | 143 +----------------- .../conditional_loop_unreachable.exp | 142 +---------------- .../inter_procedural_abort.exp | 61 +------- .../loop_unreachable.exp | 28 +--- .../return_after_abort.exp | 23 +-- 103 files changed, 366 insertions(+), 536 deletions(-) create mode 100644 third_party/move/move-compiler-v2/tests/ability-check/drop_on_abort.exp create mode 100644 third_party/move/move-compiler-v2/tests/ability-check/resources.exp create mode 100644 third_party/move/move-compiler-v2/tests/skip_attribute_checks/aptos_stdlib_attributes2.exp create mode 100644 third_party/move/move-compiler-v2/tests/skip_attribute_checks/attribute_placement.exp create mode 100644 third_party/move/move-compiler-v2/tests/skip_attribute_checks/attribute_variants.exp create mode 100644 third_party/move/move-compiler-v2/tests/skip_attribute_checks/extra_attributes.exp create mode 100644 third_party/move/move-compiler-v2/tests/skip_attribute_checks/extra_attributes2.exp create mode 100644 third_party/move/move-compiler-v2/tests/skip_attribute_checks/testonly.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/attribute_location.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/cross_module_members.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_bad_value.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_constants.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_constants_invalid.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_invalid_literals.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_not_test.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_out_of_range_value.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/extra_attributes.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/extra_attributes2.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/invalid_expected_code_name.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/invalid_expected_failure_name.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/multiple_errors.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/multiple_test_annotations.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/named_address_no_value_in_annotation.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_invalid_assignment.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_invalid_location.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_invalid_location_module.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_valid.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/test_and_test_only_annotation.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/notest/valid_test_module.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/attribute_location.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/cross_module_members.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/cross_module_members_non_test_function.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/cross_module_test_only_module.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_bad_value.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_constants.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_constants_invalid.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_invalid_literals.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_not_test.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_out_of_range_value.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/extra_attributes.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/invalid_expected_code_name.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/invalid_expected_failure_name.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_invalid_assignment.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_invalid_location.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_valid.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/test_and_test_only_annotation.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/test_filter_function.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/test_filter_struct.exp create mode 100644 third_party/move/move-compiler-v2/tests/unit_test/test/valid_test_module.exp diff --git a/third_party/move/move-compiler-v2/tests/ability-check/drop_on_abort.exp b/third_party/move/move-compiler-v2/tests/ability-check/drop_on_abort.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/ability-check/drop_on_abort.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/ability-check/resources.exp b/third_party/move/move-compiler-v2/tests/ability-check/resources.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/ability-check/resources.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/ability-check/unused_var.exp b/third_party/move/move-compiler-v2/tests/ability-check/unused_var.exp index d20fb43bef3c9..6d2401c7b4244 100644 --- a/third_party/move/move-compiler-v2/tests/ability-check/unused_var.exp +++ b/third_party/move/move-compiler-v2/tests/ability-check/unused_var.exp @@ -5,3 +5,6 @@ warning: Unused parameter `x`. Consider removing or prefixing with an underscore │ 6 │ fun unused_arg(x: T) { │ ^ + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/acquires_error_msg.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/acquires_error_msg.exp index ad9e30e775461..ea9ede1967b84 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/acquires_error_msg.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/acquires_error_msg.exp @@ -16,3 +16,6 @@ module 0x42::test { Tuple() } } // end 0x42::test + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/bug_11112.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/bug_11112.exp index 322fd8dc7421e..2d26e677fd493 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/bug_11112.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/bug_11112.exp @@ -34,3 +34,6 @@ module 0xcafe::vectors { } } } // end 0xcafe::vectors + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/bug_11223.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/bug_11223.exp index 6de110861a7f7..88ecb0c6d4f29 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/bug_11223.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/bug_11223.exp @@ -17,3 +17,6 @@ module 0xcafe::vectors { } } } // end 0xcafe::vectors + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/bug_9717.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/bug_9717.exp index 09a4d87b6d39c..f7760bc27df74 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/bug_9717.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/bug_9717.exp @@ -130,3 +130,6 @@ module 0xcafe::vectors { Tuple() } } // end 0xcafe::vectors + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/bug_9717_looponly.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/bug_9717_looponly.exp index a1bab5aa98412..0e16c76cedfe5 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/bug_9717_looponly.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/bug_9717_looponly.exp @@ -38,3 +38,6 @@ module 0xcafe::vectors { } } } // end 0xcafe::vectors + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/deep_exp.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/deep_exp.exp index 103457c42d5f2..1f461a307261e 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/deep_exp.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/deep_exp.exp @@ -4,3 +4,6 @@ module 0x42::Test { 625 } } // end 0x42::Test + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/double_nesting.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/double_nesting.exp index e5132322bc003..20557a753b0b7 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/double_nesting.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/double_nesting.exp @@ -15,3 +15,6 @@ module 0x42::test { Tuple() } } // end 0x42::test + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/inline_accessing_constant.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/inline_accessing_constant.exp index 41b76a2b90b91..990438c5c697d 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/inline_accessing_constant.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/inline_accessing_constant.exp @@ -6,3 +6,6 @@ module 0xc0ffee::dummy2 { 1 } } // end 0xc0ffee::dummy2 + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/lambda.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda.exp index 82f2a6ecb8041..e443b41e7ff18 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/lambda.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda.exp @@ -43,3 +43,6 @@ module 0x42::LambdaTest { Tuple() } } // end 0x42::LambdaTest + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_cast.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_cast.exp index a67ca1e188d4e..57cee1446037e 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_cast.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_cast.exp @@ -58,3 +58,6 @@ module 0x12391283::M { } } } // end 0x12391283::M + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/nested_mul.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/nested_mul.exp index 7f6dd9c649389..60cb5c92619f5 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/nested_mul.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/nested_mul.exp @@ -12,3 +12,6 @@ module 0x42::test { Tuple() } } // end 0x42::test + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/order_sensitive.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/order_sensitive.exp index 16f2b89c1f834..31d1d1528084a 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/order_sensitive.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/order_sensitive.exp @@ -40,3 +40,6 @@ module 0x42::OrderSensitiveTest3 { })) } } // end 0x42::OrderSensitiveTest3 + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/recursive_nesting.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/recursive_nesting.exp index ba0a03aa56369..ff680a44ad2c2 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/recursive_nesting.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/recursive_nesting.exp @@ -20,3 +20,6 @@ module 0x42::test { Tuple() } } // end 0x42::test + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/resources_invalid.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/resources_invalid.exp index 88832821857a9..289dc8cf4f230 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/resources_invalid.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/resources_invalid.exp @@ -18,3 +18,11 @@ module 0x42::token { }) } } // end 0x42::token + + +Diagnostics: +bug: struct not defined + ┌─ tests/checking/inlining/resources_invalid.move:17:16 + │ +17 │ public fun get_value(ref: &obj::ReaderRef): u64 acquires Token { + │ ^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused.exp index 23ed46173ec3d..8aa569bdd48ef 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused.exp @@ -26,3 +26,6 @@ module 0x42::Test { } } } // end 0x42::Test + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused_nodecl.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused_nodecl.exp index dd4450373fc1a..b25b35f14e5fb 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused_nodecl.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused_nodecl.exp @@ -34,3 +34,6 @@ module 0x42::Test { } } } // end 0x42::Test + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/spec_inlining.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/spec_inlining.exp index e80c54961868f..77b71777f0c74 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/spec_inlining.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/spec_inlining.exp @@ -48,3 +48,6 @@ module 0x42::Test { } } } // end 0x42::Test + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/temp_shadowing.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/temp_shadowing.exp index aa06a27a64542..67af9646754bf 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/temp_shadowing.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/temp_shadowing.exp @@ -41,3 +41,6 @@ module 0x42::Test { } } } // end 0x42::Test + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/test_12670.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/test_12670.exp index 5e31dc71a54e6..e110f2e38ae4f 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/test_12670.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/test_12670.exp @@ -29,3 +29,6 @@ module 0x1::Test { } } } // end 0x1::Test + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/unused_inline.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/unused_inline.exp index 3832853f89ade..61d7d2e1e4435 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/unused_inline.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/unused_inline.exp @@ -20,3 +20,6 @@ module 0xc0ffee::m { } } } // end 0xc0ffee::m + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/folding/constant_values.exp b/third_party/move/move-compiler-v2/tests/folding/constant_values.exp index 31646be86d937..5ff1d119edddf 100644 --- a/third_party/move/move-compiler-v2/tests/folding/constant_values.exp +++ b/third_party/move/move-compiler-v2/tests/folding/constant_values.exp @@ -19,3 +19,6 @@ module 0x8675309::M { 1 } } // end 0x8675309::M + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/folding/non_constant_empty_vec.exp b/third_party/move/move-compiler-v2/tests/folding/non_constant_empty_vec.exp index 875ed6741eeb9..2a78724f1fe13 100644 --- a/third_party/move/move-compiler-v2/tests/folding/non_constant_empty_vec.exp +++ b/third_party/move/move-compiler-v2/tests/folding/non_constant_empty_vec.exp @@ -22,3 +22,6 @@ module 0x42::M { Vector>() } } // end 0x42::M + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/no-simplifier/constant_folding_ristretto.exp b/third_party/move/move-compiler-v2/tests/no-simplifier/constant_folding_ristretto.exp index ffc4657223c95..b6a72eeed3745 100644 --- a/third_party/move/move-compiler-v2/tests/no-simplifier/constant_folding_ristretto.exp +++ b/third_party/move/move-compiler-v2/tests/no-simplifier/constant_folding_ristretto.exp @@ -15,3 +15,6 @@ module 0xcafe::Ristretto { } } } // end 0xcafe::Ristretto + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/no-simplifier/moved_var_not_simplified3.exp b/third_party/move/move-compiler-v2/tests/no-simplifier/moved_var_not_simplified3.exp index f8a87bfb50170..2158fe7059dd2 100644 --- a/third_party/move/move-compiler-v2/tests/no-simplifier/moved_var_not_simplified3.exp +++ b/third_party/move/move-compiler-v2/tests/no-simplifier/moved_var_not_simplified3.exp @@ -13,3 +13,6 @@ module 0xc0ffee::m { } } } // end 0xc0ffee::m + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/always_false_branch.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/always_false_branch.exp index b7d690e43dc92..1b0ab31f62f3e 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/always_false_branch.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/always_false_branch.exp @@ -13,3 +13,6 @@ module 0xc0ffee::m { 0 } } // end 0xc0ffee::m + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/binary_add.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/binary_add.exp index e7eba52ec1c8d..4d22f28e939cd 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/binary_add.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/binary_add.exp @@ -63,3 +63,6 @@ module 0x8675309::M { } } } // end 0x8675309::M + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/bind_with_type_annot.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/bind_with_type_annot.exp index dacb5b0be3cf7..bd47ab1047bbe 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/bind_with_type_annot.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/bind_with_type_annot.exp @@ -36,3 +36,6 @@ module 0x8675309::M { } } } // end 0x8675309::M + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/constant_all_valid_types.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/constant_all_valid_types.exp index 62bfa312532fe..a92a5c0f0eaca 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/constant_all_valid_types.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/constant_all_valid_types.exp @@ -71,3 +71,6 @@ module _0 { Tuple() } } // end _0 + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/double_nesting.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/double_nesting.exp index e5132322bc003..20557a753b0b7 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/double_nesting.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/double_nesting.exp @@ -15,3 +15,6 @@ module 0x42::test { Tuple() } } // end 0x42::test + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/else_assigns_if_doesnt.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/else_assigns_if_doesnt.exp index 4ac34e7e2ade2..5341e02a3dceb 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/else_assigns_if_doesnt.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/else_assigns_if_doesnt.exp @@ -23,3 +23,11 @@ module _0 { } } } // end _0 + + +Diagnostics: +error: use of possibly unassigned local `y` + ┌─ tests/simplifier-elimination/else_assigns_if_doesnt.move:11:13 + │ +11 │ assert!(y == 0, 42); + │ ^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_assigns_else_doesnt.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_assigns_else_doesnt.exp index efd3bd232a7b9..60725545fcc86 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_assigns_else_doesnt.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_assigns_else_doesnt.exp @@ -23,3 +23,11 @@ module _0 { } } } // end _0 + + +Diagnostics: +error: use of possibly unassigned local `x` + ┌─ tests/simplifier-elimination/if_assigns_else_doesnt.move:11:13 + │ +11 │ assert!(x == 42, 42); + │ ^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_assigns_no_else.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_assigns_no_else.exp index ea573dd8c39a5..73f3d514c0647 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_assigns_no_else.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_assigns_no_else.exp @@ -24,3 +24,6 @@ module _0 { } } } // end _0 + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_condition.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_condition.exp index d77d8e0a4b01b..d78ee58957b72 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_condition.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_condition.exp @@ -53,3 +53,6 @@ module 0x8675309::M { Tuple() } } // end 0x8675309::M + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/recursive_nesting.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/recursive_nesting.exp index ba0a03aa56369..ff680a44ad2c2 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/recursive_nesting.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/recursive_nesting.exp @@ -20,3 +20,6 @@ module 0x42::test { Tuple() } } // end 0x42::test + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign.exp index e7715ccabf3bf..ac63e9d86f699 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign.exp @@ -18,3 +18,11 @@ module _0 { } } } // end _0 + + +Diagnostics: +error: use of unassigned local `x` + ┌─ tests/simplifier-elimination/use_before_assign.move:4:13 + │ +4 │ let y = x; + │ ^ diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign_loop.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign_loop.exp index 04e5c0984a968..56337567699df 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign_loop.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign_loop.exp @@ -63,3 +63,35 @@ module 0x8675309::M { } } } // end 0x8675309::M + + +Diagnostics: +error: use of possibly unassigned local `x` + ┌─ tests/simplifier-elimination/use_before_assign_loop.move:4:24 + │ +4 │ loop { let y = move x + 1; x = 0; y; } + │ ^^^^^^ + +error: use of possibly unassigned local `x` + ┌─ tests/simplifier-elimination/use_before_assign_loop.move:9:24 + │ +9 │ loop { let y = x + 1; if (cond) { continue }; x = 0; y; } + │ ^^^^^ + +error: use of possibly unassigned local `x` + ┌─ tests/simplifier-elimination/use_before_assign_loop.move:14:24 + │ +14 │ loop { let y = &x; _ = move y; x = 0 } + │ ^^ + +error: use of unassigned local `x` + ┌─ tests/simplifier-elimination/use_before_assign_loop.move:19:24 + │ +19 │ loop { let y = &x; _ = move y; if (cond) { x = 0 }; break }; + │ ^^ + +error: use of possibly unassigned local `x` + ┌─ tests/simplifier-elimination/use_before_assign_loop.move:20:9 + │ +20 │ x; + │ ^ diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign_while.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign_while.exp index 26da21abbf036..223526a98870c 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign_while.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign_while.exp @@ -79,6 +79,32 @@ module 0x8675309::M { } // end 0x8675309::M +Diagnostics: +error: use of possibly unassigned local `x` + ┌─ tests/simplifier-elimination/use_before_assign_while.move:4:32 + │ +4 │ while (cond) { let y = move x + 1; x = 0; y; } + │ ^^^^^^ + +error: use of possibly unassigned local `x` + ┌─ tests/simplifier-elimination/use_before_assign_while.move:9:32 + │ +9 │ while (cond) { let y = move x + 1; if (cond) { continue }; x = 0; y; } + │ ^^^^^^ + +error: use of possibly unassigned local `x` + ┌─ tests/simplifier-elimination/use_before_assign_while.move:14:32 + │ +14 │ while (cond) { let y = &x; _ = move y; x = 0 } + │ ^^ + +error: use of unassigned local `x` + ┌─ tests/simplifier-elimination/use_before_assign_while.move:19:32 + │ +19 │ while (cond) { let y = &x; _ = move y; if (cond) { x = 0 }; break } + │ ^^ + + Diagnostics: error: cannot move local `x` since it is still in use ┌─ tests/simplifier-elimination/use_before_assign_while.move:9:32 diff --git a/third_party/move/move-compiler-v2/tests/simplifier/bug_11112.exp b/third_party/move/move-compiler-v2/tests/simplifier/bug_11112.exp index 322fd8dc7421e..2d26e677fd493 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier/bug_11112.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier/bug_11112.exp @@ -34,3 +34,6 @@ module 0xcafe::vectors { } } } // end 0xcafe::vectors + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/simplifier/conditional_borrow.exp b/third_party/move/move-compiler-v2/tests/simplifier/conditional_borrow.exp index 8dd2d677df781..fe3356ff35068 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier/conditional_borrow.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier/conditional_borrow.exp @@ -95,3 +95,6 @@ module 0x8675::M { Add(M::test1b(pack M::S(7)), M::test1b(pack M::S(2))) } } // end 0x8675::M + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/simplifier/constant_folding_ristretto.exp b/third_party/move/move-compiler-v2/tests/simplifier/constant_folding_ristretto.exp index 23170b251e269..bf7ddb3eda7a4 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier/constant_folding_ristretto.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier/constant_folding_ristretto.exp @@ -9,3 +9,6 @@ module 0xcafe::Ristretto { Tuple() } } // end 0xcafe::Ristretto + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/simplifier/deep_exp.exp b/third_party/move/move-compiler-v2/tests/simplifier/deep_exp.exp index 103457c42d5f2..1f461a307261e 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier/deep_exp.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier/deep_exp.exp @@ -4,3 +4,6 @@ module 0x42::Test { 625 } } // end 0x42::Test + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test1.exp b/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test1.exp index ba31566abd4aa..17267d722a3a2 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test1.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test1.exp @@ -28,3 +28,6 @@ module 0x8675::M { } } } // end 0x8675::M + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test2.exp b/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test2.exp index 38ae1ecd3dc74..ce0ec6cdb8cd0 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test2.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test2.exp @@ -28,3 +28,6 @@ module 0x8675::M { } } } // end 0x8675::M + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test3.exp b/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test3.exp index bbfdba9bdbe4e..be956d2fdd85f 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test3.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test3.exp @@ -28,3 +28,6 @@ module 0x8675::M { } } } // end 0x8675::M + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/skip_attribute_checks/aptos_stdlib_attributes2.exp b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/aptos_stdlib_attributes2.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/aptos_stdlib_attributes2.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/skip_attribute_checks/attribute_placement.exp b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/attribute_placement.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/attribute_placement.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/skip_attribute_checks/attribute_variants.exp b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/attribute_variants.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/attribute_variants.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/skip_attribute_checks/extra_attributes.exp b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/extra_attributes.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/extra_attributes.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/skip_attribute_checks/extra_attributes2.exp b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/extra_attributes2.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/extra_attributes2.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/skip_attribute_checks/testonly.exp b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/testonly.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/skip_attribute_checks/testonly.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/testsuite.rs b/third_party/move/move-compiler-v2/tests/testsuite.rs index facbc70e85dca..f227a4f4c0eda 100644 --- a/third_party/move/move-compiler-v2/tests/testsuite.rs +++ b/third_party/move/move-compiler-v2/tests/testsuite.rs @@ -38,8 +38,8 @@ struct TestConfig { runner: fn(&Path) -> datatest_stable::Result<()>, /// Path substring for tests to include. include: Vec<&'static str>, - /// Path substring for tests to exclude. The set of tests included is that - /// which match any of the include strings and do _not_ match ony of + /// Path substring for tests to exclude. The set of tests included are those + /// which match any of the include strings and do _not_ match any of /// the exclude strings. exclude: Vec<&'static str>, /// If set, a suffix for the baseline file used for these tests. @@ -176,12 +176,9 @@ const TEST_CONFIGS: Lazy> = Lazy::new(|| { exp_suffix: None, options: opts .clone() - .set_experiment(Experiment::AST_SIMPLIFY_FULL, true) - // TODO: this check should not need to be turned off, but some - // tests rely on it. Those tests should be fixed. - .set_experiment(Experiment::UNINITIALIZED_CHECK, false), - // Run the full bytecode pipeline as well for double-checking the result - stop_after: StopAfter::BytecodePipeline(None), + .set_experiment(Experiment::AST_SIMPLIFY_FULL, true), + // Run the entire compiler pipeline to double-check the result + stop_after: StopAfter::FileFormat, dump_ast: DumpLevel::EndStage, dump_bytecode: DumpLevel::None, // do not dump anything dump_bytecode_filter: None, @@ -194,8 +191,8 @@ const TEST_CONFIGS: Lazy> = Lazy::new(|| { exclude: vec![], exp_suffix: None, options: opts.clone().set_experiment(Experiment::AST_SIMPLIFY, true), - // Run the bytecode pipeline as well for double-checking the result - stop_after: StopAfter::BytecodePipeline(None), + // Run the entire compiler pipeline to double-check the result + stop_after: StopAfter::FileFormat, dump_ast: DumpLevel::EndStage, dump_bytecode: DumpLevel::None, // do not dump anything dump_bytecode_filter: None, @@ -208,8 +205,8 @@ const TEST_CONFIGS: Lazy> = Lazy::new(|| { exclude: vec![], exp_suffix: None, options: opts.clone().set_experiment(Experiment::AST_SIMPLIFY, false), - // Run the bytecode pipeline as well for double-checking the result - stop_after: StopAfter::BytecodePipeline(None), + // Run the entire compiler pipeline to double-check the result + stop_after: StopAfter::FileFormat, dump_ast: DumpLevel::EndStage, dump_bytecode: DumpLevel::None, // do not dump anything dump_bytecode_filter: None, @@ -305,7 +302,8 @@ const TEST_CONFIGS: Lazy> = Lazy::new(|| { exclude: vec![], exp_suffix: None, options: opts.clone(), - stop_after: StopAfter::BytecodePipeline(None), + // Run the entire compiler pipeline to double-check the result + stop_after: StopAfter::FileFormat, dump_ast: DumpLevel::None, dump_bytecode: DumpLevel::None, dump_bytecode_filter: None, @@ -336,7 +334,8 @@ const TEST_CONFIGS: Lazy> = Lazy::new(|| { exclude: vec![], exp_suffix: None, options: opts.clone(), - stop_after: StopAfter::AstPipeline, + // Run the full compiler pipeline to double-check the result. + stop_after: StopAfter::FileFormat, dump_ast: DumpLevel::None, dump_bytecode: DumpLevel::None, dump_bytecode_filter: None, @@ -433,10 +432,9 @@ const TEST_CONFIGS: Lazy> = Lazy::new(|| { include: vec!["/unreachable-code-remover/"], exclude: vec![], exp_suffix: None, - options: opts - .clone() - .set_experiment(Experiment::ABILITY_CHECK, false), - stop_after: StopAfter::BytecodePipeline(None), + options: opts.clone(), + // Run the entire compiler pipeline to double-check the result + stop_after: StopAfter::FileFormat, dump_ast: DumpLevel::None, dump_bytecode: DumpLevel::AllStages, dump_bytecode_filter: Some(vec![ @@ -501,7 +499,8 @@ const TEST_CONFIGS: Lazy> = Lazy::new(|| { .clone() .set_experiment(Experiment::AST_SIMPLIFY, true) .set_compile_test_code(true), - stop_after: StopAfter::BytecodePipeline(None), + // Run the entire compiler pipeline to double-check the result + stop_after: StopAfter::FileFormat, dump_ast: DumpLevel::None, dump_bytecode: DumpLevel::None, dump_bytecode_filter: None, @@ -516,7 +515,8 @@ const TEST_CONFIGS: Lazy> = Lazy::new(|| { .clone() .set_experiment(Experiment::AST_SIMPLIFY, true) .set_compile_test_code(false), - stop_after: StopAfter::BytecodePipeline(None), + // Run the entire compiler pipeline to double-check the result + stop_after: StopAfter::FileFormat, dump_ast: DumpLevel::None, dump_bytecode: DumpLevel::None, dump_bytecode_filter: None, @@ -531,7 +531,8 @@ const TEST_CONFIGS: Lazy> = Lazy::new(|| { .clone() .set_experiment(Experiment::AST_SIMPLIFY, true) .set_skip_attribute_checks(true), - stop_after: StopAfter::BytecodePipeline(None), + // Run the entire compiler pipeline to double-check the result + stop_after: StopAfter::FileFormat, dump_ast: DumpLevel::None, dump_bytecode: DumpLevel::None, dump_bytecode_filter: None, diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/attribute_location.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/attribute_location.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/attribute_location.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/cross_module_members.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/cross_module_members.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/cross_module_members.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_bad_value.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_bad_value.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_bad_value.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_constants.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_constants.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_constants.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_constants_invalid.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_constants_invalid.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_constants_invalid.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_invalid_literals.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_invalid_literals.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_invalid_literals.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_not_test.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_not_test.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_not_test.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_out_of_range_value.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_out_of_range_value.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/expected_failure_out_of_range_value.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/extra_attributes.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/extra_attributes.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/extra_attributes.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/extra_attributes2.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/extra_attributes2.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/extra_attributes2.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/invalid_expected_code_name.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/invalid_expected_code_name.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/invalid_expected_code_name.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/invalid_expected_failure_name.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/invalid_expected_failure_name.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/invalid_expected_failure_name.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/multiple_errors.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/multiple_errors.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/multiple_errors.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/multiple_test_annotations.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/multiple_test_annotations.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/multiple_test_annotations.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/named_address_no_value_in_annotation.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/named_address_no_value_in_annotation.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/named_address_no_value_in_annotation.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_invalid_assignment.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_invalid_assignment.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_invalid_assignment.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_invalid_location.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_invalid_location.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_invalid_location.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_invalid_location_module.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_invalid_location_module.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_invalid_location_module.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_valid.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_valid.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/other_failures_valid.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/test_and_test_only_annotation.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/test_and_test_only_annotation.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/test_and_test_only_annotation.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/notest/valid_test_module.exp b/third_party/move/move-compiler-v2/tests/unit_test/notest/valid_test_module.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/notest/valid_test_module.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/attribute_location.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/attribute_location.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/attribute_location.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/cross_module_members.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/cross_module_members.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/cross_module_members.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/cross_module_members_non_test_function.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/cross_module_members_non_test_function.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/cross_module_members_non_test_function.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/cross_module_test_only_module.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/cross_module_test_only_module.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/cross_module_test_only_module.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_bad_value.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_bad_value.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_bad_value.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_constants.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_constants.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_constants.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_constants_invalid.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_constants_invalid.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_constants_invalid.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_invalid_literals.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_invalid_literals.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_invalid_literals.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_not_test.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_not_test.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_not_test.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_out_of_range_value.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_out_of_range_value.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/expected_failure_out_of_range_value.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/extra_attributes.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/extra_attributes.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/extra_attributes.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/invalid_expected_code_name.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/invalid_expected_code_name.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/invalid_expected_code_name.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/invalid_expected_failure_name.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/invalid_expected_failure_name.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/invalid_expected_failure_name.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_invalid_assignment.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_invalid_assignment.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_invalid_assignment.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_invalid_location.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_invalid_location.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_invalid_location.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_valid.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_valid.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/other_failures_valid.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/test_and_test_only_annotation.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/test_and_test_only_annotation.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/test_and_test_only_annotation.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/test_filter_function.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/test_filter_function.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/test_filter_function.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/test_filter_struct.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/test_filter_struct.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/test_filter_struct.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unit_test/test/valid_test_module.exp b/third_party/move/move-compiler-v2/tests/unit_test/test/valid_test_module.exp new file mode 100644 index 0000000000000..90b32906711cc --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/unit_test/test/valid_test_module.exp @@ -0,0 +1,2 @@ + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/abort_only.exp b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/abort_only.exp index a73344034dcb8..85735ce6435d1 100644 --- a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/abort_only.exp +++ b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/abort_only.exp @@ -13,25 +13,10 @@ fun m::test() { [variant baseline] fun m::test() { var $t0: u64 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 0: $t0 := 0 - # live vars: $t0 - # graph: {} - # locals: {} - # globals: {} - # # maybe 1: abort($t0) - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # no 2: return () } @@ -44,3 +29,6 @@ fun m::test() { 0: $t0 := 0 1: abort($t0) } + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/abort_or_return_always.exp b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/abort_or_return_always.exp index 0dbecb205f7dc..42049d7c5387c 100644 --- a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/abort_or_return_always.exp +++ b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/abort_or_return_always.exp @@ -23,81 +23,26 @@ fun m::test($t0: bool): u64 { fun m::test($t0: bool): u64 { var $t1: u64 var $t2: u64 - # live vars: $t0 - # graph: {} - # locals: {} - # globals: {} - # # maybe 0: if ($t0) goto 1 else goto 5 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 1: label L0 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 2: $t2 := 0 - # live vars: $t2 - # graph: {} - # locals: {} - # globals: {} - # # maybe 3: abort($t2) - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # no 4: goto 8 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 5: label L1 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 6: $t1 := 1 - # live vars: $t1 - # graph: {} - # locals: {} - # globals: {} - # # maybe 7: return $t1 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # no 8: label L2 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # no 9: $t1 := 42 - # live vars: $t1 - # graph: {} - # locals: {} - # globals: {} - # # no 10: return $t1 } @@ -116,3 +61,6 @@ fun m::test($t0: bool): u64 { 5: $t1 := 1 6: return $t1 } + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/always_false_branch.exp b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/always_false_branch.exp index dd20af0333aa0..b55ae11ddad2f 100644 --- a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/always_false_branch.exp +++ b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/always_false_branch.exp @@ -32,102 +32,32 @@ fun m::test(): u64 { var $t2: u64 var $t3: u64 var $t4: u64 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 0: $t1 := false - # live vars: $t1 - # graph: {} - # locals: {} - # globals: {} - # # maybe 1: if ($t1) goto 2 else goto 10 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 2: label L0 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 3: $t2 := 0 - # live vars: $t2 - # graph: {} - # locals: {} - # globals: {} - # # maybe 4: $t4 := 1 - # live vars: $t2, $t4 - # graph: {} - # locals: {} - # globals: {} - # # maybe 5: $t3 := +($t2, $t4) - # live vars: $t3 - # graph: {} - # locals: {} - # globals: {} - # # maybe - 6: $t2 := infer($t3) - # live vars: $t2 - # graph: {} - # locals: {} - # globals: {} - # + 6: $t2 := move($t3) # maybe - 7: $t0 := infer($t2) - # live vars: $t0 - # graph: {} - # locals: {} - # globals: {} - # + 7: $t0 := move($t2) # maybe 8: return $t0 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # no 9: goto 11 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 10: label L1 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 11: label L2 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 12: $t0 := 0 - # live vars: $t0 - # graph: {} - # locals: {} - # globals: {} - # # maybe 13: return $t0 } @@ -147,11 +77,14 @@ fun m::test(): u64 { 3: $t2 := 0 4: $t4 := 1 5: $t3 := +($t2, $t4) - 6: $t2 := infer($t3) - 7: $t0 := infer($t2) + 6: $t2 := move($t3) + 7: $t0 := move($t2) 8: return $t0 9: label L1 10: label L2 11: $t0 := 0 12: return $t0 } + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/break_unreachable.exp b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/break_unreachable.exp index f16341968c3b2..cb8e1cd1f4259 100644 --- a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/break_unreachable.exp +++ b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/break_unreachable.exp @@ -56,186 +56,56 @@ fun m::test() { var $t8: u64 var $t9: u64 var $t10: u64 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 0: $t0 := 0 - # live vars: $t0 - # graph: {} - # locals: {} - # globals: {} - # # maybe 1: label L0 - # live vars: $t0 - # graph: {} - # locals: {} - # globals: {} - # # maybe 2: $t2 := 1 - # live vars: $t0, $t2 - # graph: {} - # locals: {} - # globals: {} - # # maybe 3: $t1 := +($t0, $t2) - # live vars: $t1 - # graph: {} - # locals: {} - # globals: {} - # # maybe - 4: $t0 := infer($t1) - # live vars: $t0 - # graph: {} - # locals: {} - # globals: {} - # + 4: $t0 := move($t1) # maybe 5: $t4 := 10 - # live vars: $t0, $t4 - # graph: {} - # locals: {} - # globals: {} - # # maybe 6: $t3 := ==($t0, $t4) - # live vars: $t0, $t3 - # graph: {} - # locals: {} - # globals: {} - # # maybe 7: if ($t3) goto 8 else goto 14 - # live vars: $t0 - # graph: {} - # locals: {} - # globals: {} - # # maybe 8: label L2 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 9: goto 24 - # live vars: $t0 - # graph: {} - # locals: {} - # globals: {} - # # no 10: $t6 := 1 - # live vars: $t0, $t6 - # graph: {} - # locals: {} - # globals: {} - # # no 11: $t5 := +($t0, $t6) - # live vars: $t5 - # graph: {} - # locals: {} - # globals: {} - # # no - 12: $t0 := infer($t5) - # live vars: $t0 - # graph: {} - # locals: {} - # globals: {} - # + 12: $t0 := move($t5) # no 13: goto 19 - # live vars: $t0 - # graph: {} - # locals: {} - # globals: {} - # # maybe 14: label L3 - # live vars: $t0 - # graph: {} - # locals: {} - # globals: {} - # # maybe 15: goto 1 - # live vars: $t0 - # graph: {} - # locals: {} - # globals: {} - # # no 16: $t8 := 1 - # live vars: $t0, $t8 - # graph: {} - # locals: {} - # globals: {} - # # no 17: $t7 := +($t0, $t8) - # live vars: $t7 - # graph: {} - # locals: {} - # globals: {} - # # no - 18: $t0 := infer($t7) - # live vars: $t0 - # graph: {} - # locals: {} - # globals: {} - # + 18: $t0 := move($t7) # no 19: label L4 - # live vars: $t0 - # graph: {} - # locals: {} - # globals: {} - # # no 20: $t10 := 1 - # live vars: $t0, $t10 - # graph: {} - # locals: {} - # globals: {} - # # no 21: $t9 := +($t0, $t10) - # live vars: $t9 - # graph: {} - # locals: {} - # globals: {} - # # no - 22: $t0 := infer($t9) - # live vars: $t0 - # graph: {} - # locals: {} - # globals: {} - # + 22: $t0 := move($t9) # no 23: goto 1 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 24: label L1 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 25: return () } @@ -259,7 +129,7 @@ fun m::test() { 1: label L0 2: $t2 := 1 3: $t1 := +($t0, $t2) - 4: $t0 := infer($t1) + 4: $t0 := move($t1) 5: $t4 := 10 6: $t3 := ==($t0, $t4) 7: if ($t3) goto 8 else goto 10 @@ -270,3 +140,6 @@ fun m::test() { 12: label L1 13: return () } + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/conditional_loop_unreachable.exp b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/conditional_loop_unreachable.exp index 4290e3c293d8f..189a01e97ca64 100644 --- a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/conditional_loop_unreachable.exp +++ b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/conditional_loop_unreachable.exp @@ -47,193 +47,58 @@ fun m::test($t0: bool, $t1: bool) { var $t5: u64 var $t6: u64 var $t7: u64 - # live vars: $t0, $t1 - # graph: {} - # locals: {} - # globals: {} - # # maybe 0: label L0 - # live vars: $t0, $t1 - # graph: {} - # locals: {} - # globals: {} - # # maybe 1: if ($t0) goto 2 else goto 21 - # live vars: $t1 - # graph: {} - # locals: {} - # globals: {} - # # maybe 2: label L2 - # live vars: $t1 - # graph: {} - # locals: {} - # globals: {} - # # maybe 3: if ($t1) goto 4 else goto 13 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 4: label L5 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 5: label L8 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 6: goto 5 - # live vars: $t0, $t1 - # graph: {} - # locals: {} - # globals: {} - # # no 7: label L9 - # live vars: $t0, $t1 - # graph: {} - # locals: {} - # globals: {} - # # no 8: $t2 := 0 - # live vars: $t0, $t1, $t2 - # graph: {} - # locals: {} - # globals: {} - # # no 9: $t4 := 1 - # live vars: $t0, $t1, $t2, $t4 - # graph: {} - # locals: {} - # globals: {} - # # no 10: $t3 := +($t2, $t4) - # live vars: $t0, $t1, $t3 - # graph: {} - # locals: {} - # globals: {} - # # no - 11: $t2 := infer($t3) - # live vars: $t0, $t1 - # graph: {} - # locals: {} - # globals: {} - # + 11: $t2 := move($t3) # no 12: goto 15 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 13: label L6 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 14: goto 25 - # live vars: $t0, $t1 - # graph: {} - # locals: {} - # globals: {} - # # no 15: label L7 - # live vars: $t0, $t1 - # graph: {} - # locals: {} - # globals: {} - # # no 16: $t5 := 0 - # live vars: $t0, $t1, $t5 - # graph: {} - # locals: {} - # globals: {} - # # no 17: $t7 := 1 - # live vars: $t0, $t1, $t5, $t7 - # graph: {} - # locals: {} - # globals: {} - # # no 18: $t6 := +($t5, $t7) - # live vars: $t0, $t1, $t6 - # graph: {} - # locals: {} - # globals: {} - # # no - 19: $t5 := infer($t6) - # live vars: $t0, $t1 - # graph: {} - # locals: {} - # globals: {} - # + 19: $t5 := move($t6) # no 20: goto 23 - # live vars: $t1 - # graph: {} - # locals: {} - # globals: {} - # # maybe 21: label L3 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 22: goto 25 - # live vars: $t0, $t1 - # graph: {} - # locals: {} - # globals: {} - # # no 23: label L4 - # live vars: $t0, $t1 - # graph: {} - # locals: {} - # globals: {} - # # no 24: goto 0 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 25: label L1 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 26: return () } @@ -262,3 +127,6 @@ fun m::test($t0: bool, $t1: bool) { 11: label L1 12: return () } + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/inter_procedural_abort.exp b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/inter_procedural_abort.exp index 742c9f709abef..13b2dfac8f0df 100644 --- a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/inter_procedural_abort.exp +++ b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/inter_procedural_abort.exp @@ -29,25 +29,10 @@ fun m::test(): u64 { [variant baseline] fun m::always_abort() { var $t0: u64 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 0: $t0 := 0 - # live vars: $t0 - # graph: {} - # locals: {} - # globals: {} - # # maybe 1: abort($t0) - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # no 2: return () } @@ -59,53 +44,18 @@ fun m::test(): u64 { var $t1: u64 var $t2: u64 var $t3: u64 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 0: m::always_abort() - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 1: $t1 := 0 - # live vars: $t1 - # graph: {} - # locals: {} - # globals: {} - # # maybe 2: $t3 := 1 - # live vars: $t1, $t3 - # graph: {} - # locals: {} - # globals: {} - # # maybe 3: $t2 := +($t1, $t3) - # live vars: $t2 - # graph: {} - # locals: {} - # globals: {} - # # maybe - 4: $t1 := infer($t2) - # live vars: $t1 - # graph: {} - # locals: {} - # globals: {} - # + 4: $t1 := move($t2) # maybe - 5: $t0 := infer($t1) - # live vars: $t0 - # graph: {} - # locals: {} - # globals: {} - # + 5: $t0 := move($t1) # maybe 6: return $t0 } @@ -130,7 +80,10 @@ fun m::test(): u64 { 1: $t1 := 0 2: $t3 := 1 3: $t2 := +($t1, $t3) - 4: $t1 := infer($t2) - 5: $t0 := infer($t1) + 4: $t1 := move($t2) + 5: $t0 := move($t1) 6: return $t0 } + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/loop_unreachable.exp b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/loop_unreachable.exp index 95258527b00ab..821dbaf362d9b 100644 --- a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/loop_unreachable.exp +++ b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/loop_unreachable.exp @@ -15,39 +15,14 @@ fun m::test(): u64 { [variant baseline] fun m::test(): u64 { var $t0: u64 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 0: label L0 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 1: goto 0 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # no 2: label L1 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # no 3: $t0 := 42 - # live vars: $t0 - # graph: {} - # locals: {} - # globals: {} - # # no 4: return $t0 } @@ -60,3 +35,6 @@ fun m::test(): u64 { 0: label L0 1: goto 0 } + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/return_after_abort.exp b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/return_after_abort.exp index 26e0f5e98e35b..2386a577129e6 100644 --- a/third_party/move/move-compiler-v2/tests/unreachable-code-remover/return_after_abort.exp +++ b/third_party/move/move-compiler-v2/tests/unreachable-code-remover/return_after_abort.exp @@ -16,32 +16,12 @@ fun m::test(): u32 { fun m::test(): u32 { var $t0: u32 var $t1: u64 - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # maybe 0: $t1 := 0 - # live vars: $t1 - # graph: {} - # locals: {} - # globals: {} - # # maybe 1: abort($t1) - # live vars: - # graph: {} - # locals: {} - # globals: {} - # # no 2: $t0 := 0 - # live vars: $t0 - # graph: {} - # locals: {} - # globals: {} - # # no 3: return $t0 } @@ -55,3 +35,6 @@ fun m::test(): u32 { 0: $t1 := 0 1: abort($t1) } + + +============ bytecode verification succeeded ======== From be0ef975cee078cd7215b3aea346b2d02fb0843d Mon Sep 17 00:00:00 2001 From: Josh Lind Date: Tue, 9 Apr 2024 17:16:53 -0400 Subject: [PATCH 34/36] [CI/CD] Adopt targeted CLI windows build test. --- .../rust-targeted-unit-tests/action.yaml | 2 +- .github/workflows/windows-build.yaml | 22 +++- devtools/aptos-cargo-cli/src/cargo.rs | 4 +- devtools/aptos-cargo-cli/src/lib.rs | 120 +++++++++++++++--- 4 files changed, 120 insertions(+), 28 deletions(-) diff --git a/.github/actions/rust-targeted-unit-tests/action.yaml b/.github/actions/rust-targeted-unit-tests/action.yaml index aaadf0cea9d05..e3948ba59dd49 100644 --- a/.github/actions/rust-targeted-unit-tests/action.yaml +++ b/.github/actions/rust-targeted-unit-tests/action.yaml @@ -36,7 +36,7 @@ runs: # Run only the targeted rust unit tests - name: Run only the targeted unit tests run: | - cargo x targeted-unit-tests -vv run --profile ci --cargo-profile ci --locked --no-fail-fast --retries 3 + cargo x targeted-unit-tests -vv --profile ci --cargo-profile ci --locked --no-fail-fast --retries 3 shell: bash env: INDEXER_DATABASE_URL: postgresql://postgres@localhost/postgres diff --git a/.github/workflows/windows-build.yaml b/.github/workflows/windows-build.yaml index ab39f05db2e70..e276fe5b9b84c 100644 --- a/.github/workflows/windows-build.yaml +++ b/.github/workflows/windows-build.yaml @@ -23,7 +23,10 @@ jobs: run: shell: pwsh steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 # Fetch all git history for accurate target determination # This action will cache ~/.cargo and ./target (or the equivalent on Windows in # this case). See more here: @@ -41,8 +44,17 @@ jobs: - name: Install OpenSSL run: vcpkg install openssl:x64-windows-static-md --clean-after-build - - name: Build the Aptos CLI - run: cargo build -p aptos + # Output the changed files + - name: Output the changed files + run: cargo x changed-files -vv + shell: bash - - name: Run the Aptos CLI help command - run: cargo run -p aptos -- --help + # Output the affected packages + - name: Output the affected packages + run: cargo x affected-packages -vv + shell: bash + + # Build and test the Aptos CLI (if it has changed) + - name: Build and test the CLI + run: cargo x targeted-cli-tests -vv + shell: bash diff --git a/devtools/aptos-cargo-cli/src/cargo.rs b/devtools/aptos-cargo-cli/src/cargo.rs index c3fbcbcc388df..0621754a267ec 100644 --- a/devtools/aptos-cargo-cli/src/cargo.rs +++ b/devtools/aptos-cargo-cli/src/cargo.rs @@ -46,7 +46,7 @@ impl Cargo { self } - pub fn run(&mut self) { + pub fn run(&mut self, ignore_failed_exit_status: bool) { // Set up the output and arguments self.inner.stdout(Stdio::inherit()).stderr(Stdio::inherit()); if !self.pass_through_args.is_empty() { @@ -64,7 +64,7 @@ impl Cargo { // This will ensure that failures are not dropped silently. match result { Ok(output) => { - if !output.status.success() { + if !ignore_failed_exit_status && !output.status.success() { panic!( "Command failed: {:?}. Output: {:?}", command_to_execute, output diff --git a/devtools/aptos-cargo-cli/src/lib.rs b/devtools/aptos-cargo-cli/src/lib.rs index f77d425a78791..54ef2047800f8 100644 --- a/devtools/aptos-cargo-cli/src/lib.rs +++ b/devtools/aptos-cargo-cli/src/lib.rs @@ -5,11 +5,14 @@ mod cargo; mod common; use cargo::Cargo; -use clap::{Args, Parser, Subcommand}; +use clap::{command, Args, Parser, Subcommand}; pub use common::SelectedPackageArgs; use determinator::Utf8Paths0; use log::{debug, trace}; +// The CLI package name to match against for targeted CLI tests +const APTOS_CLI_PACKAGE_NAME: &str = "aptos"; + // The targeted unit test packages to ignore (these will be run separately, by other jobs) const TARGETED_TEST_PACKAGES_TO_IGNORE: [&str; 2] = ["aptos-testcases", "smoke-test"]; @@ -39,6 +42,7 @@ pub enum AptosCargoCommand { Xclippy(CommonArgs), Fmt(CommonArgs), Nextest(CommonArgs), + TargetedCLITests(CommonArgs), TargetedUnitTests(CommonArgs), Test(CommonArgs), } @@ -50,7 +54,6 @@ impl AptosCargoCommand { AptosCargoCommand::Xclippy(_) => "clippy", AptosCargoCommand::Fmt(_) => "fmt", AptosCargoCommand::Nextest(_) => "nextest", - AptosCargoCommand::TargetedUnitTests(_) => "nextest", // Invoke the nextest command directly AptosCargoCommand::Test(_) => "test", command => panic!("Unsupported command attempted! Command: {:?}", command), } @@ -64,6 +67,7 @@ impl AptosCargoCommand { AptosCargoCommand::Xclippy(args) => args, AptosCargoCommand::Fmt(args) => args, AptosCargoCommand::Nextest(args) => args, + AptosCargoCommand::TargetedCLITests(args) => args, AptosCargoCommand::TargetedUnitTests(args) => args, AptosCargoCommand::Test(args) => args, } @@ -121,42 +125,70 @@ impl AptosCargoCommand { let (_, _, changed_files) = package_args.identify_changed_files()?; output_changed_files(changed_files) }, + AptosCargoCommand::TargetedCLITests(_) => { + // Calculate the affected packages and run the targeted CLI tests (if any). + // Start by fetching the affected packages. + let packages = package_args.compute_target_packages()?; + + // Check if the affected packages contains the Aptos CLI + let mut cli_affected = false; + for package_path in packages { + // Extract the package name from the full path + let package_name = get_package_name_from_path(&package_path); + + // Check if the package is the Aptos CLI + if package_name == APTOS_CLI_PACKAGE_NAME { + cli_affected = true; + break; + } + } + + // If the Aptos CLI is affected, run the targeted CLI tests + if cli_affected { + println!("Running the targeted CLI tests..."); + return run_targeted_cli_tests(); + } + + // Otherwise, skip the CLI tests + println!("Skipping CLI tests as the Aptos CLI package was not affected!"); + Ok(()) + }, AptosCargoCommand::TargetedUnitTests(_) => { - // Calculate and run the targeted unit tests. + // Calculate the affected packages and run the targeted unit tests (if any). // Start by fetching the arguments and affected packages. - let (mut direct_args, push_through_args, packages) = + let (direct_args, push_through_args, packages) = self.get_args_and_affected_packages(package_args)?; - // Add each affected package to the arguments, but filter out - // the packages that should not be run as unit tests. - let mut found_package_to_test = false; + // Collect all the affected packages to test, but filter out the packages + // that should not be run as unit tests. + let mut packages_to_test = vec![]; for package_path in packages { // Extract the package name from the full path - let package_name = package_path.split('#').last().unwrap(); + let package_name = get_package_name_from_path(&package_path); // Only add the package if it is not in the ignore list - if TARGETED_TEST_PACKAGES_TO_IGNORE.contains(&package_name) { + if TARGETED_TEST_PACKAGES_TO_IGNORE.contains(&package_name.as_str()) { debug!( "Ignoring package when running targeted-unit-tests: {:?}", package_name ); } else { - // Add the arguments for the package - direct_args.push("-p".into()); - direct_args.push(package_path); - - // Mark that we found a package to test - found_package_to_test = true; + packages_to_test.push(package_path); } } - // Create and run the command if we found a package to test - if found_package_to_test { + // Create and run the command if we found packages to test + if !packages_to_test.is_empty() { println!("Running the targeted unit tests..."); - return self.create_and_run_command(direct_args, push_through_args); + return run_targeted_unit_tests( + packages_to_test, + direct_args, + push_through_args, + ); } - println!("Skipping targeted unit tests because no packages were affected to test."); + // Otherwise, skip the targeted unit tests + println!("Skipping targeted unit tests because no test packages were affected!"); Ok(()) }, _ => { @@ -196,12 +228,60 @@ impl AptosCargoCommand { // Construct and run the final command let mut command = Cargo::command(self.command()); command.args(direct_args).pass_through(push_through_args); - command.run(); + command.run(false); Ok(()) } } +/// Returns the package name from the given package path +fn get_package_name_from_path(package_path: &str) -> String { + package_path.split('#').last().unwrap().to_string() +} + +/// Runs the targeted CLI tests. This includes building and testing the CLI. +fn run_targeted_cli_tests() -> anyhow::Result<()> { + // First, run the CLI tests + let mut command = Cargo::command("test"); + command.args(["-p", APTOS_CLI_PACKAGE_NAME]); + command.run(false); + + // Next, build the CLI binary + let mut command = Cargo::command("build"); + command.args(["-p", APTOS_CLI_PACKAGE_NAME]); + command.run(false); + + // Finally, run the CLI --help command. Here, we ignore the exit status + // because the CLI will return a non-zero exit status when running --help. + let mut command = Cargo::command("run"); + command.args(["-p", APTOS_CLI_PACKAGE_NAME]); + command.run(true); + + Ok(()) +} + +/// Runs the targeted unit tests. This includes building and testing the unit tests. +fn run_targeted_unit_tests( + packages_to_test: Vec, + mut direct_args: Vec, + push_through_args: Vec, +) -> anyhow::Result<()> { + // Add each package to the arguments + for package in packages_to_test { + direct_args.push("-p".into()); + direct_args.push(package); + } + + // Create the command to run the unit tests + let mut command = Cargo::command("nextest"); + command.args(["run"]); + command.args(direct_args).pass_through(push_through_args); + + // Run the unit tests + command.run(false); + Ok(()) +} + /// Outputs the specified affected packages fn output_affected_packages(packages: Vec) -> anyhow::Result<()> { // Output the affected packages (if they exist) From 59586fee4ebb88d659f0f74afa094d728cf32b5d Mon Sep 17 00:00:00 2001 From: Teng Zhang Date: Wed, 10 Apr 2024 16:29:45 -0700 Subject: [PATCH 35/36] [Compiler-v2] check access for structs (#12821) * check field * handle comments --- .../move-compiler-v2/src/function_checker.rs | 124 +++++++++++++++++- .../{ => v1-typing}/invalid_type_acquire.exp | 12 +- .../{ => v1-typing}/invalid_type_acquire.move | 0 .../checking/inlining/resources_invalid.exp | 28 +--- .../checking/typing/borrow_field_internal.exp | 38 +++--- .../typing/global_builtins_script.exp | 39 +++--- .../implicit_deref_borrow_field_internal.exp | 38 +++--- .../checking/typing/mutate_field_internal.exp | 38 +++--- .../move/move-compiler-v2/tests/testsuite.rs | 3 +- .../move/move-compiler-v2/tests/v1.matched | 36 +---- .../move/move-compiler-v2/tests/v1.unmatched | 17 --- .../visibility-checker/global_operator.exp | 73 +++++++++++ .../visibility-checker/global_operator.move | 31 +++++ .../pack_unpack_structs.exp | 51 +++++++ .../pack_unpack_structs.move | 24 ++++ .../resource_operator_inline.exp | 78 +++++++++++ .../resource_operator_inline.move | 77 +++++++++++ .../visibility-checker/resources_invalid.exp | 12 ++ .../visibility-checker/resources_invalid.move | 20 +++ .../v1-typing/pack_private_with_field.exp | 15 +++ .../v1-typing/pack_private_with_field.move | 28 ++++ .../v1-typing/pack_unpack_private.exp | 17 +++ .../v1-typing/pack_unpack_private.move | 13 ++ .../v1-typing/pack_unpack_private_script.exp | 18 +++ .../v1-typing/pack_unpack_private_script.move | 15 +++ .../tools/testdiff/src/main.rs | 4 + 26 files changed, 690 insertions(+), 159 deletions(-) rename third_party/move/move-compiler-v2/tests/checking-lang-v1/{ => v1-typing}/invalid_type_acquire.exp (69%) rename third_party/move/move-compiler-v2/tests/checking-lang-v1/{ => v1-typing}/invalid_type_acquire.move (100%) create mode 100644 third_party/move/move-compiler-v2/tests/visibility-checker/global_operator.exp create mode 100644 third_party/move/move-compiler-v2/tests/visibility-checker/global_operator.move create mode 100644 third_party/move/move-compiler-v2/tests/visibility-checker/pack_unpack_structs.exp create mode 100644 third_party/move/move-compiler-v2/tests/visibility-checker/pack_unpack_structs.move create mode 100644 third_party/move/move-compiler-v2/tests/visibility-checker/resource_operator_inline.exp create mode 100644 third_party/move/move-compiler-v2/tests/visibility-checker/resource_operator_inline.move create mode 100644 third_party/move/move-compiler-v2/tests/visibility-checker/resources_invalid.exp create mode 100644 third_party/move/move-compiler-v2/tests/visibility-checker/resources_invalid.move create mode 100644 third_party/move/move-compiler-v2/tests/visibility-checker/v1-typing/pack_private_with_field.exp create mode 100644 third_party/move/move-compiler-v2/tests/visibility-checker/v1-typing/pack_private_with_field.move create mode 100644 third_party/move/move-compiler-v2/tests/visibility-checker/v1-typing/pack_unpack_private.exp create mode 100644 third_party/move/move-compiler-v2/tests/visibility-checker/v1-typing/pack_unpack_private.move create mode 100644 third_party/move/move-compiler-v2/tests/visibility-checker/v1-typing/pack_unpack_private_script.exp create mode 100644 third_party/move/move-compiler-v2/tests/visibility-checker/v1-typing/pack_unpack_private_script.move diff --git a/third_party/move/move-compiler-v2/src/function_checker.rs b/third_party/move/move-compiler-v2/src/function_checker.rs index fb4d3e7dd7f97..3248c07fade94 100644 --- a/third_party/move/move-compiler-v2/src/function_checker.rs +++ b/third_party/move/move-compiler-v2/src/function_checker.rs @@ -7,7 +7,8 @@ use crate::Options; use codespan_reporting::diagnostic::Severity; use move_binary_format::file_format::Visibility; use move_model::{ - model::{FunId, FunctionEnv, GlobalEnv, Loc, NodeId, QualifiedId}, + ast::{ExpData, Operation, Pattern}, + model::{FunId, FunctionEnv, GlobalEnv, Loc, ModuleEnv, NodeId, QualifiedId}, ty::Type, }; use std::{collections::BTreeSet, iter::Iterator, vec::Vec}; @@ -56,6 +57,123 @@ pub fn check_for_function_typed_parameters(env: &mut GlobalEnv) { } } +fn access_error( + env: &GlobalEnv, + fun_loc: &Loc, + id: &NodeId, + oper: &str, + msg: String, + module_env: &ModuleEnv, +) { + let call_details: Vec<_> = [*id] + .iter() + .map(|node_id| (env.get_node_loc(*node_id), format!("{} here", oper))) + .collect(); + let msg = format!( + "Invalid operation: {} can only be done within the defining module `{}`", + msg, + module_env.get_full_name_str() + ); + env.diag_with_labels(Severity::Error, fun_loc, &msg, call_details); +} + +/// check privileged operations on a struct such as storage operation, pack/unpack and field accesses +/// can only be performed within the module that defines it. +fn check_privileged_operations_on_structs(env: &GlobalEnv, fun_env: &FunctionEnv) { + if let Some(fun_body) = fun_env.get_def() { + let caller_module_id = fun_env.module_env.get_id(); + fun_body.visit_pre_order(&mut |exp: &ExpData| { + match exp { + ExpData::Call(id, oper, _) => match oper { + Operation::Exists(_) + | Operation::BorrowGlobal(_) + | Operation::MoveFrom + | Operation::MoveTo => { + let inst = env.get_node_instantiation(*id); + debug_assert!(!inst.is_empty()); + if let Some((struct_env, _)) = inst[0].get_struct(env) { + let mid = struct_env.module_env.get_id(); + let sid = struct_env.get_id(); + if mid != caller_module_id { + let qualified_struct_id = mid.qualified(sid); + let struct_env = env.get_struct(qualified_struct_id); + access_error( + env, + &fun_env.get_id_loc(), + id, + "called", + format!( + "storage operation on type `{}`", + struct_env.get_full_name_str(), + ), + &struct_env.module_env, + ); + } + } + }, + Operation::Select(mid, sid, fid) if *mid != caller_module_id => { + let qualified_struct_id = mid.qualified(*sid); + let struct_env = env.get_struct(qualified_struct_id); + access_error( + env, + &fun_env.get_id_loc(), + id, + "accessed", + format!( + "access of the field `{}` on type `{}`", + fid.symbol().display(struct_env.symbol_pool()), + struct_env.get_full_name_str(), + ), + &struct_env.module_env, + ); + }, + Operation::Pack(mid, sid) => { + if *mid != caller_module_id { + let qualified_struct_id = mid.qualified(*sid); + let struct_env = env.get_struct(qualified_struct_id); + access_error( + env, + &fun_env.get_id_loc(), + id, + "packed", + format!("pack of `{}`", struct_env.get_full_name_str(),), + &struct_env.module_env, + ); + } + }, + _ => {}, + }, + ExpData::Assign(_, pat, _) + | ExpData::Block(_, pat, _, _) + | ExpData::Lambda(_, pat, _) => { + pat.visit_pre_post(&mut |_, pat| { + if let Pattern::Struct(id, str, _) = pat { + let module_id = str.module_id; + if module_id != caller_module_id { + let struct_env = env.get_struct(str.to_qualified_id()); + access_error( + env, + &fun_env.get_id_loc(), + id, + "unpacked", + format!("unpack of `{}`", struct_env.get_full_name_str(),), + &struct_env.module_env, + ); + } + } + }); + }, + // access in specs is not restricted + ExpData::SpecBlock(_, _) => { + return false; + }, + _ => {}, + } + true + }); + } +} + /// For all function in target modules: /// /// If `before_inlining`, then @@ -63,6 +181,7 @@ pub fn check_for_function_typed_parameters(env: &mut GlobalEnv) { /// - warn about unused private functions /// Otherwise (`!before_inlining`): /// - check that all function calls *not* involving inline functions are accessible. +/// - check privileged operations on structs cannot be done across module boundary pub fn check_access_and_use(env: &mut GlobalEnv, before_inlining: bool) { // For each function seen, we record whether it has an accessible caller. let mut functions_with_callers: BTreeSet = BTreeSet::new(); @@ -77,6 +196,9 @@ pub fn check_access_and_use(env: &mut GlobalEnv, before_inlining: bool) { let caller_module_has_friends = !caller_module.has_no_friends(); let caller_module_is_script = caller_module.get_name().is_script(); for caller_func in caller_module.get_functions() { + if !before_inlining { + check_privileged_operations_on_structs(env, &caller_func); + } let caller_qfid = caller_func.get_qualified_id(); // During first pass, record private functions for later diff --git a/third_party/move/move-compiler-v2/tests/checking-lang-v1/invalid_type_acquire.exp b/third_party/move/move-compiler-v2/tests/checking-lang-v1/v1-typing/invalid_type_acquire.exp similarity index 69% rename from third_party/move/move-compiler-v2/tests/checking-lang-v1/invalid_type_acquire.exp rename to third_party/move/move-compiler-v2/tests/checking-lang-v1/v1-typing/invalid_type_acquire.exp index b3ed2abde218f..2c8415cbb4dbd 100644 --- a/third_party/move/move-compiler-v2/tests/checking-lang-v1/invalid_type_acquire.exp +++ b/third_party/move/move-compiler-v2/tests/checking-lang-v1/v1-typing/invalid_type_acquire.exp @@ -1,31 +1,31 @@ Diagnostics: error: invalid access specifier - ┌─ tests/checking-lang-v1/invalid_type_acquire.move:18:9 + ┌─ tests/checking-lang-v1/v1-typing/invalid_type_acquire.move:18:9 │ 18 │ T, │ ^ error: not supported before language version `2.0-unstable`: address and wildcard access specifiers. Only resource type names can be provided. - ┌─ tests/checking-lang-v1/invalid_type_acquire.move:18:9 + ┌─ tests/checking-lang-v1/v1-typing/invalid_type_acquire.move:18:9 │ 18 │ T, │ ^ error: invalid access specifier - ┌─ tests/checking-lang-v1/invalid_type_acquire.move:19:9 + ┌─ tests/checking-lang-v1/v1-typing/invalid_type_acquire.move:19:9 │ 19 │ u64, │ ^^^ error: not supported before language version `2.0-unstable`: address and wildcard access specifiers. Only resource type names can be provided. - ┌─ tests/checking-lang-v1/invalid_type_acquire.move:19:9 + ┌─ tests/checking-lang-v1/v1-typing/invalid_type_acquire.move:19:9 │ 19 │ u64, │ ^^^ error: type `u64` is missing required ability `key` - ┌─ tests/checking-lang-v1/invalid_type_acquire.move:32:36 + ┌─ tests/checking-lang-v1/v1-typing/invalid_type_acquire.move:32:36 │ 32 │ destroy(account, move_from(a)); │ ^^^ @@ -33,7 +33,7 @@ error: type `u64` is missing required ability `key` = required by instantiating type parameter `T:key` of function `move_from` error: type `S` is missing required ability `key` - ┌─ tests/checking-lang-v1/invalid_type_acquire.move:34:36 + ┌─ tests/checking-lang-v1/v1-typing/invalid_type_acquire.move:34:36 │ 34 │ destroy(account, move_from(a)); │ ^ diff --git a/third_party/move/move-compiler-v2/tests/checking-lang-v1/invalid_type_acquire.move b/third_party/move/move-compiler-v2/tests/checking-lang-v1/v1-typing/invalid_type_acquire.move similarity index 100% rename from third_party/move/move-compiler-v2/tests/checking-lang-v1/invalid_type_acquire.move rename to third_party/move/move-compiler-v2/tests/checking-lang-v1/v1-typing/invalid_type_acquire.move diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/resources_invalid.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/resources_invalid.exp index 289dc8cf4f230..ff822cd8995f5 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/resources_invalid.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/resources_invalid.exp @@ -1,28 +1,12 @@ -// -- Model dump before bytecode pipeline -module 0x42::objects { - struct ReaderRef { - addr: address, - } -} // end 0x42::objects -module 0x42::token { - use 0x42::objects as obj; // resolved as: 0x42::objects - struct Token { - val: u64, - } - public fun get_value(ref: &objects::ReaderRef): u64 - acquires token::Token(*) - { - select token::Token.val<&token::Token>({ - let (ref: &objects::ReaderRef): (&objects::ReaderRef) = Tuple(ref); - BorrowGlobal(Immutable)(select objects::ReaderRef.addr<&objects::ReaderRef>(ref)) - }) - } -} // end 0x42::token - Diagnostics: -bug: struct not defined +error: Invalid operation: access of the field `addr` on type `objects::ReaderRef` can only be done within the defining module `0x42::objects` ┌─ tests/checking/inlining/resources_invalid.move:17:16 │ + 8 │ borrow_global(ref.addr) + │ -------- accessed here + · 17 │ public fun get_value(ref: &obj::ReaderRef): u64 acquires Token { │ ^^^^^^^^^ +18 │ obj::reader(ref).val + │ ---------------- from a call inlined at this callsite diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/borrow_field_internal.exp b/third_party/move/move-compiler-v2/tests/checking/typing/borrow_field_internal.exp index 7cf7ab7d87c3a..b0bad9e39e752 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/borrow_field_internal.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/borrow_field_internal.exp @@ -1,20 +1,18 @@ -// -- Model dump before bytecode pipeline -module 0x2::X { - struct S { - f: u64, - } - public fun s(): X::S { - pack X::S(0) - } -} // end 0x2::X -module 0x2::M { - use 0x2::X; // resolved as: 0x2::X - private fun t0() { - Borrow(Immutable)(select X::S.f(X::s())); - { - let s: &X::S = Borrow(Immutable)(X::s()); - Borrow(Immutable)(select X::S.f<&X::S>(s)); - Abort(0) - } - } -} // end 0x2::M + +Diagnostics: +error: Invalid operation: access of the field `f` on type `X::S` can only be done within the defining module `0x2::X` + ┌─ tests/checking/typing/borrow_field_internal.move:12:9 + │ +12 │ fun t0() { + │ ^^ +13 │ (&X::s().f: &u64); + │ -------- accessed here + +error: Invalid operation: access of the field `f` on type `X::S` can only be done within the defining module `0x2::X` + ┌─ tests/checking/typing/borrow_field_internal.move:12:9 + │ +12 │ fun t0() { + │ ^^ + · +15 │ (&s.f: &u64); + │ --- accessed here diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/global_builtins_script.exp b/third_party/move/move-compiler-v2/tests/checking/typing/global_builtins_script.exp index 8089a2fe7cb57..b25d0a8fdccd4 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/global_builtins_script.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/global_builtins_script.exp @@ -1,20 +1,19 @@ -// -- Model dump before bytecode pipeline -module 0x42::M { - struct R { - dummy_field: bool, - } - public fun new(): M::R { - pack M::R(false) - } -} // end 0x42::M -module _0 { - use 0x42::M; // resolved as: 0x42::M - private fun test(account: signer) { - { - let r: M::R = M::new(); - BorrowGlobal(Immutable)(0x1); - MoveTo(Borrow(Immutable)(account), r); - Tuple() - } - } -} // end _0 + +Diagnostics: +error: Invalid operation: storage operation on type `M::R` can only be done within the defining module `0x42::M` + ┌─ tests/checking/typing/global_builtins_script.move:14:5 + │ +14 │ fun test(account: signer) { + │ ^^^^ +15 │ let r = M::new(); +16 │ borrow_global(@0x1); + │ ------------------------- called here + +error: Invalid operation: storage operation on type `M::R` can only be done within the defining module `0x42::M` + ┌─ tests/checking/typing/global_builtins_script.move:14:5 + │ +14 │ fun test(account: signer) { + │ ^^^^ + · +17 │ move_to(&account, r); + │ -------------------- called here diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_internal.exp b/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_internal.exp index 5a9034982e31b..b0d96087db374 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_internal.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_internal.exp @@ -1,20 +1,18 @@ -// -- Model dump before bytecode pipeline -module 0x2::X { - struct S { - f: u64, - } - public fun s(): X::S { - pack X::S(0) - } -} // end 0x2::X -module 0x2::M { - use 0x2::X; // resolved as: 0x2::X - private fun t0() { - select X::S.f(X::s()); - { - let s: &X::S = Borrow(Immutable)(X::s()); - select X::S.f<&X::S>(s); - Abort(0) - } - } -} // end 0x2::M + +Diagnostics: +error: Invalid operation: access of the field `f` on type `X::S` can only be done within the defining module `0x2::X` + ┌─ tests/checking/typing/implicit_deref_borrow_field_internal.move:12:9 + │ +12 │ fun t0() { + │ ^^ +13 │ (X::s().f: u64); + │ -------- accessed here + +error: Invalid operation: access of the field `f` on type `X::S` can only be done within the defining module `0x2::X` + ┌─ tests/checking/typing/implicit_deref_borrow_field_internal.move:12:9 + │ +12 │ fun t0() { + │ ^^ + · +15 │ (s.f: u64); + │ --- accessed here diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/mutate_field_internal.exp b/third_party/move/move-compiler-v2/tests/checking/typing/mutate_field_internal.exp index 49ad3d6aef41a..7d2bf8f3c5692 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/mutate_field_internal.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/mutate_field_internal.exp @@ -1,20 +1,18 @@ -// -- Model dump before bytecode pipeline -module 0x2::X { - struct S { - f: u64, - } - public fun s(): X::S { - pack X::S(0) - } -} // end 0x2::X -module 0x2::M { - use 0x2::X; // resolved as: 0x2::X - private fun t0() { - select X::S.f(X::s()) = 0; - { - let s: &mut X::S = Borrow(Mutable)(X::s()); - select X::S.f<&mut X::S>(s) = 0; - Abort(0) - } - } -} // end 0x2::M + +Diagnostics: +error: Invalid operation: access of the field `f` on type `X::S` can only be done within the defining module `0x2::X` + ┌─ tests/checking/typing/mutate_field_internal.move:12:9 + │ +12 │ fun t0() { + │ ^^ +13 │ X::s().f = 0; + │ -------- accessed here + +error: Invalid operation: access of the field `f` on type `X::S` can only be done within the defining module `0x2::X` + ┌─ tests/checking/typing/mutate_field_internal.move:12:9 + │ +12 │ fun t0() { + │ ^^ + · +15 │ s.f = 0; + │ --- accessed here diff --git a/third_party/move/move-compiler-v2/tests/testsuite.rs b/third_party/move/move-compiler-v2/tests/testsuite.rs index f227a4f4c0eda..cc386406f6db2 100644 --- a/third_party/move/move-compiler-v2/tests/testsuite.rs +++ b/third_party/move/move-compiler-v2/tests/testsuite.rs @@ -333,7 +333,8 @@ const TEST_CONFIGS: Lazy> = Lazy::new(|| { include: vec!["/acquires-checker/"], exclude: vec![], exp_suffix: None, - options: opts.clone(), + // Skip access check to avoid error message change in the acquires-checker + options: opts.clone().set_experiment(Experiment::ACCESS_CHECK, false), // Run the full compiler pipeline to double-check the result. stop_after: StopAfter::FileFormat, dump_ast: DumpLevel::None, diff --git a/third_party/move/move-compiler-v2/tests/v1.matched b/third_party/move/move-compiler-v2/tests/v1.matched index aaf091180c6c3..ff88c6b752220 100644 --- a/third_party/move/move-compiler-v2/tests/v1.matched +++ b/third_party/move/move-compiler-v2/tests/v1.matched @@ -319,7 +319,7 @@ move-compiler/tests/move_check/typing/implicit_deref_borrow_field_internal.exp move-compiler/tests/move_check/typing/implicit_deref_borrow_field_missing.exp move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_missing.exp move-compiler/tests/move_check/typing/implicit_deref_borrow_field_non_ref_non_local_root.exp move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_non_ref_non_local_root.exp move-compiler/tests/move_check/typing/implicit_deref_borrow_field_non_ref_root.exp move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_non_ref_root.exp -move-compiler/tests/move_check/typing/invalid_type_acquire.exp move-compiler-v2/tests/acquires-checker/v1-tests/invalid_type_acquire.exp +move-compiler/tests/move_check/typing/invalid_type_acquire.exp move-compiler-v2/tests/checking-lang-v1/v1-typing/invalid_type_acquire.exp move-compiler/tests/move_check/typing/lambda.exp move-compiler-v2/tests/checking/typing/lambda.exp move-compiler/tests/move_check/typing/large_binop.exp move-compiler-v2/tests/checking/typing/large_binop.exp move-compiler/tests/move_check/typing/loop_body.exp move-compiler-v2/tests/checking/typing/loop_body.exp @@ -363,8 +363,11 @@ move-compiler/tests/move_check/typing/pack.exp move-compiler-v2/tests/checking move-compiler/tests/move_check/typing/pack_invalid_argument.exp move-compiler-v2/tests/checking/typing/pack_invalid_argument.exp move-compiler/tests/move_check/typing/pack_missing_field.exp move-compiler-v2/tests/checking/typing/pack_missing_field.exp move-compiler/tests/move_check/typing/pack_multiple.exp move-compiler-v2/tests/checking/typing/pack_multiple.exp +move-compiler/tests/move_check/typing/pack_private_with_field.exp move-compiler-v2/tests/visibility-checker/v1-typing/pack_private_with_field.exp move-compiler/tests/move_check/typing/pack_reference.exp move-compiler-v2/tests/checking/typing/pack_reference.exp move-compiler/tests/move_check/typing/pack_unit.exp move-compiler-v2/tests/checking/typing/pack_unit.exp +move-compiler/tests/move_check/typing/pack_unpack_private.exp move-compiler-v2/tests/visibility-checker/v1-typing/pack_unpack_private.exp +move-compiler/tests/move_check/typing/pack_unpack_private_script.exp move-compiler-v2/tests/visibility-checker/v1-typing/pack_unpack_private_script.exp move-compiler/tests/move_check/typing/phantom_param_op_abilities.exp move-compiler-v2/tests/checking/abilities/v1/phantom_param_op_abilities.exp move-compiler/tests/move_check/typing/phantom_param_op_abilities_invalid.exp move-compiler-v2/tests/checking/abilities/v1/phantom_param_op_abilities_invalid.exp move-compiler/tests/move_check/typing/phantom_params_constraint_abilities.exp move-compiler-v2/tests/checking/abilities/v1/phantom_params_constraint_abilities.exp @@ -430,34 +433,3 @@ move-compiler/tests/move_check/typing/while_body.exp move-compiler-v2/tests/ch move-compiler/tests/move_check/typing/while_body_invalid.exp move-compiler-v2/tests/checking/typing/while_body_invalid.exp move-compiler/tests/move_check/typing/while_condition.exp move-compiler-v2/tests/checking/typing/while_condition.exp move-compiler/tests/move_check/typing/while_condition_invalid.exp move-compiler-v2/tests/checking/typing/while_condition_invalid.exp -move-compiler/tests/move_check/parser/aptos_stdlib_attributes.exp move-compiler-v2/tests/checking/attributes/aptos_stdlib_attributes.exp -move-compiler/tests/move_check/parser/aptos_stdlib_attributes2.exp move-compiler-v2/tests/checking/attributes/aptos_stdlib_attributes2.exp -move-compiler/tests/move_check/parser/attribute_no_closing_bracket.exp move-compiler-v2/tests/checking/attributes/attribute_no_closing_bracket.exp -move-compiler/tests/move_check/parser/attribute_num_sign_no_bracket.exp move-compiler-v2/tests/checking/attributes/attribute_num_sign_no_bracket.exp -move-compiler/tests/move_check/parser/attribute_placement.exp move-compiler-v2/tests/checking/attributes/attribute_placement.exp -move-compiler/tests/move_check/parser/attribute_variants.exp move-compiler-v2/tests/checking/attributes/attribute_variants.exp -move-compiler/tests/move_check/parser/duplicate_attributes.exp move-compiler-v2/tests/checking/attributes/duplicate_attributes.exp -move-compiler/tests/move_check/skip_attribute_checks/aptos_stdlib_attributes.exp move-compiler-v2/tests/skip_attribute_checks/aptos_stdlib_attributes.exp -move-compiler/tests/move_check/skip_attribute_checks/attribute_no_closing_bracket.exp move-compiler-v2/tests/skip_attribute_checks/attribute_no_closing_bracket.exp -move-compiler/tests/move_check/skip_attribute_checks/duplicate_attributes.exp move-compiler-v2/tests/skip_attribute_checks/duplicate_attributes.exp -move-compiler/tests/move_check/unit_testattribute_location_invalid.exp move-compiler-v2/tests/unit_test/notest/attribute_location_invalid.exp -move-compiler/tests/move_check/unit_testcross_module_members_non_test_function.exp move-compiler-v2/tests/unit_test/notest/cross_module_members_non_test_function.exp -move-compiler/tests/move_check/unit_testcross_module_test_only_module.exp move-compiler-v2/tests/unit_test/notest/cross_module_test_only_module.exp -move-compiler/tests/move_check/unit_testexpected_failure_on_non_function.exp move-compiler-v2/tests/unit_test/notest/expected_failure_on_non_function.exp -move-compiler/tests/move_check/unit_testscript_with_multiple_on_main.exp move-compiler-v2/tests/unit_test/notest/script_with_multiple_on_main.exp -move-compiler/tests/move_check/unit_testscript_with_multiple_top_level.exp move-compiler-v2/tests/unit_test/notest/script_with_multiple_top_level.exp -move-compiler/tests/move_check/unit_testscript_with_test_on_main.exp move-compiler-v2/tests/unit_test/notest/script_with_test_on_main.exp -move-compiler/tests/move_check/unit_testscript_with_test_top_level.exp move-compiler-v2/tests/unit_test/notest/script_with_test_top_level.exp -move-compiler/tests/move_check/unit_testtest_filter_function.exp move-compiler-v2/tests/unit_test/notest/test_filter_function.exp -move-compiler/tests/move_check/unit_testtest_filter_struct.exp move-compiler-v2/tests/unit_test/notest/test_filter_struct.exp -move-compiler/tests/move_check/unit_test/attribute_location_invalid.unit_test.exp move-compiler-v2/tests/unit_test/test/attribute_location_invalid.exp -move-compiler/tests/move_check/unit_test/expected_failure_on_non_function.unit_test.exp move-compiler-v2/tests/unit_test/test/expected_failure_on_non_function.exp -move-compiler/tests/move_check/unit_test/extra_attributes2.unit_test.exp move-compiler-v2/tests/unit_test/test/extra_attributes2.exp -move-compiler/tests/move_check/unit_test/multiple_errors.unit_test.exp move-compiler-v2/tests/unit_test/test/multiple_errors.exp -move-compiler/tests/move_check/unit_test/multiple_test_annotations.unit_test.exp move-compiler-v2/tests/unit_test/test/multiple_test_annotations.exp -move-compiler/tests/move_check/unit_test/named_address_no_value_in_annotation.unit_test.exp move-compiler-v2/tests/unit_test/test/named_address_no_value_in_annotation.exp -move-compiler/tests/move_check/unit_test/other_failures_invalid_location_module.unit_test.exp move-compiler-v2/tests/unit_test/test/other_failures_invalid_location_module.exp -move-compiler/tests/move_check/unit_test/script_with_multiple_on_main.unit_test.exp move-compiler-v2/tests/unit_test/test/script_with_multiple_on_main.exp -move-compiler/tests/move_check/unit_test/script_with_multiple_top_level.unit_test.exp move-compiler-v2/tests/unit_test/test/script_with_multiple_top_level.exp -move-compiler/tests/move_check/unit_test/script_with_test_on_main.unit_test.exp move-compiler-v2/tests/unit_test/test/script_with_test_on_main.exp -move-compiler/tests/move_check/unit_test/script_with_test_top_level.unit_test.exp move-compiler-v2/tests/unit_test/test/script_with_test_top_level.exp diff --git a/third_party/move/move-compiler-v2/tests/v1.unmatched b/third_party/move/move-compiler-v2/tests/v1.unmatched index 0600fe2512c01..a8870f551fdf9 100644 --- a/third_party/move/move-compiler-v2/tests/v1.unmatched +++ b/third_party/move/move-compiler-v2/tests/v1.unmatched @@ -205,9 +205,6 @@ move-compiler/tests/move_check/typing/{ mutable_eq_and_neq_invalid.move, non_phantom_in_phantom_pos.move, pack_constraint_not_satisfied.move, - pack_private_with_field.move, - pack_unpack_private.move, - pack_unpack_private_script.move, pay_me_a_river.move, phantom_param_struct_decl.move, phantom_param_struct_decl_invalid.move, @@ -225,17 +222,3 @@ move-compiler/tests/move_check/verification/{ single_module_invalid.move, single_module_valid.move, } -move-compiler/tests/move_check/unit_test/{ - cross_module_members_non_test_function.move - expected_failure_bad_value.unit_test - expected_failure_constants_invalid.unit_test - expected_failure_invalid_literals.unit_test - expected_failure_not_test.unit_test - expected_failure_out_of_range_value.unit_test - extra_attributes.unit_test - invalid_expected_code_name.unit_test - invalid_expected_failure_name.unit_test - other_failures_invalid_assignment.unit_test - other_failures_invalid_location.unit_test - test_and_test_only_annotation.unit_test -} diff --git a/third_party/move/move-compiler-v2/tests/visibility-checker/global_operator.exp b/third_party/move/move-compiler-v2/tests/visibility-checker/global_operator.exp new file mode 100644 index 0000000000000..2c1e20b0af572 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/visibility-checker/global_operator.exp @@ -0,0 +1,73 @@ + +Diagnostics: +error: Invalid operation: storage operation on type `M::R` can only be done within the defining module `0x42::M` + ┌─ tests/visibility-checker/global_operator.move:10:9 + │ +10 │ fun test(account: signer) { + │ ^^^^ +11 │ let r = M::new(); +12 │ borrow_global(@0x1); + │ ------------------------- called here + +error: Invalid operation: storage operation on type `M::R` can only be done within the defining module `0x42::M` + ┌─ tests/visibility-checker/global_operator.move:10:9 + │ +10 │ fun test(account: signer) { + │ ^^^^ + · +13 │ borrow_global_mut(@0x1); + │ ----------------------------- called here + +error: Invalid operation: storage operation on type `M::R` can only be done within the defining module `0x42::M` + ┌─ tests/visibility-checker/global_operator.move:10:9 + │ +10 │ fun test(account: signer) { + │ ^^^^ + · +14 │ exists(@0x1); + │ ------------------ called here + +error: Invalid operation: storage operation on type `M::R` can only be done within the defining module `0x42::M` + ┌─ tests/visibility-checker/global_operator.move:10:9 + │ +10 │ fun test(account: signer) { + │ ^^^^ + · +15 │ move_to(&account, r); + │ -------------------- called here + +error: Invalid operation: storage operation on type `M::R` can only be done within the defining module `0x42::M` + ┌─ tests/visibility-checker/global_operator.move:24:9 + │ +24 │ fun test(account: signer) { + │ ^^^^ +25 │ let r = M::new(); +26 │ borrow_global(@0x1); + │ ------------------------- called here + +error: Invalid operation: storage operation on type `M::R` can only be done within the defining module `0x42::M` + ┌─ tests/visibility-checker/global_operator.move:24:9 + │ +24 │ fun test(account: signer) { + │ ^^^^ + · +27 │ borrow_global_mut(@0x1); + │ ----------------------------- called here + +error: Invalid operation: storage operation on type `M::R` can only be done within the defining module `0x42::M` + ┌─ tests/visibility-checker/global_operator.move:24:9 + │ +24 │ fun test(account: signer) { + │ ^^^^ + · +28 │ exists(@0x1); + │ ------------------ called here + +error: Invalid operation: storage operation on type `M::R` can only be done within the defining module `0x42::M` + ┌─ tests/visibility-checker/global_operator.move:24:9 + │ +24 │ fun test(account: signer) { + │ ^^^^ + · +29 │ move_to(&account, r); + │ -------------------- called here diff --git a/third_party/move/move-compiler-v2/tests/visibility-checker/global_operator.move b/third_party/move/move-compiler-v2/tests/visibility-checker/global_operator.move new file mode 100644 index 0000000000000..6ad6a8f361e8a --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/visibility-checker/global_operator.move @@ -0,0 +1,31 @@ +address 0x42 { +module M { + struct R has key {} + public fun new(): R { + R {} + } +} +module M2 { + use 0x42::M; + fun test(account: signer) { + let r = M::new(); + borrow_global(@0x1); + borrow_global_mut(@0x1); + exists(@0x1); + move_to(&account, r); + } +} +} + + +script { + use 0x42::M; + + fun test(account: signer) { + let r = M::new(); + borrow_global(@0x1); + borrow_global_mut(@0x1); + exists(@0x1); + move_to(&account, r); + } +} diff --git a/third_party/move/move-compiler-v2/tests/visibility-checker/pack_unpack_structs.exp b/third_party/move/move-compiler-v2/tests/visibility-checker/pack_unpack_structs.exp new file mode 100644 index 0000000000000..7b41593f009c7 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/visibility-checker/pack_unpack_structs.exp @@ -0,0 +1,51 @@ + +Diagnostics: +error: Invalid operation: pack of `D::G` can only be done within the defining module `0x41::D` + ┌─ tests/visibility-checker/pack_unpack_structs.move:13:16 + │ +13 │ public fun foo(): C::T { + │ ^^^ +14 │ C::T {g: G{}} + │ --- packed here + +error: Invalid operation: pack of `C::T` can only be done within the defining module `0x43::C` + ┌─ tests/visibility-checker/pack_unpack_structs.move:13:16 + │ +13 │ public fun foo(): C::T { + │ ^^^ +14 │ C::T {g: G{}} + │ ------------- packed here + +error: Invalid operation: unpack of `C::T` can only be done within the defining module `0x43::C` + ┌─ tests/visibility-checker/pack_unpack_structs.move:16:16 + │ +16 │ public fun bar(c: C::T) { + │ ^^^ +17 │ let C::T { g } = c; + │ ---------- unpacked here + +error: Invalid operation: unpack of `D::G` can only be done within the defining module `0x41::D` + ┌─ tests/visibility-checker/pack_unpack_structs.move:16:16 + │ +16 │ public fun bar(c: C::T) { + │ ^^^ +17 │ let C::T { g } = c; +18 │ let G {} = g; + │ ---- unpacked here + +error: Invalid operation: unpack of `C::T` can only be done within the defining module `0x43::C` + ┌─ tests/visibility-checker/pack_unpack_structs.move:20:16 + │ +20 │ public fun bar_ref(c: &C::T) { + │ ^^^^^^^ +21 │ let C::T { g } = c; + │ ---------- unpacked here + +error: Invalid operation: unpack of `D::G` can only be done within the defining module `0x41::D` + ┌─ tests/visibility-checker/pack_unpack_structs.move:20:16 + │ +20 │ public fun bar_ref(c: &C::T) { + │ ^^^^^^^ +21 │ let C::T { g } = c; +22 │ let G {} = g; + │ ---- unpacked here diff --git a/third_party/move/move-compiler-v2/tests/visibility-checker/pack_unpack_structs.move b/third_party/move/move-compiler-v2/tests/visibility-checker/pack_unpack_structs.move new file mode 100644 index 0000000000000..90894329128cb --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/visibility-checker/pack_unpack_structs.move @@ -0,0 +1,24 @@ +module 0x43::C { + use 0x41::D; + struct T {g: D::G} +} + +module 0x41::D { + struct G {} +} + +module 0x42::B { + use 0x43::C; + use 0x41::D::G; + public fun foo(): C::T { + C::T {g: G{}} + } + public fun bar(c: C::T) { + let C::T { g } = c; + let G {} = g; + } + public fun bar_ref(c: &C::T) { + let C::T { g } = c; + let G {} = g; + } +} diff --git a/third_party/move/move-compiler-v2/tests/visibility-checker/resource_operator_inline.exp b/third_party/move/move-compiler-v2/tests/visibility-checker/resource_operator_inline.exp new file mode 100644 index 0000000000000..7403790beb25d --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/visibility-checker/resource_operator_inline.exp @@ -0,0 +1,78 @@ + +Diagnostics: +error: Invalid operation: storage operation on type `M::R` can only be done within the defining module `0x42::M` + ┌─ tests/visibility-checker/resource_operator_inline.move:45:9 + │ +14 │ borrow_global(addr) + │ ---------------------- called here + · +45 │ fun test_borrow() { + │ ^^^^^^^^^^^ +46 │ M::inline_borrow(@0x42); + │ ----------------------- from a call inlined at this callsite + +error: Invalid operation: storage operation on type `M::R` can only be done within the defining module `0x42::M` + ┌─ tests/visibility-checker/resource_operator_inline.move:49:9 + │ +18 │ borrow_global_mut(addr) + │ -------------------------- called here + · +49 │ fun test_borrow_mut() { + │ ^^^^^^^^^^^^^^^ +50 │ M::inline_borrow_mut(@0x42); + │ --------------------------- from a call inlined at this callsite + +error: Invalid operation: storage operation on type `M::R` can only be done within the defining module `0x42::M` + ┌─ tests/visibility-checker/resource_operator_inline.move:53:9 + │ +22 │ move_to(account, r) + │ ---------------------- called here + · +53 │ fun test_move_to(account: signer) { + │ ^^^^^^^^^^^^ +54 │ let r = M::new(); +55 │ M::inline_move_to(&account, r); + │ ------------------------------ from a call inlined at this callsite + +error: Invalid operation: storage operation on type `M::R` can only be done within the defining module `0x42::M` + ┌─ tests/visibility-checker/resource_operator_inline.move:58:9 + │ +26 │ move_from(addr) + │ ------------------ called here + · +58 │ fun test_move_from(addr: address) { + │ ^^^^^^^^^^^^^^ +59 │ M::inline_move_from(addr); + │ ------------------------- from a call inlined at this callsite + +error: Invalid operation: pack of `M::R` can only be done within the defining module `0x42::M` + ┌─ tests/visibility-checker/resource_operator_inline.move:62:9 + │ +30 │ R {} + │ ---- packed here + · +62 │ fun test_inline_pack() { + │ ^^^^^^^^^^^^^^^^ +63 │ M::inline_pack(); + │ ---------------- from a call inlined at this callsite + +error: Invalid operation: unpack of `M::R` can only be done within the defining module `0x42::M` + ┌─ tests/visibility-checker/resource_operator_inline.move:66:9 + │ +34 │ let R{} = r; + │ --- unpacked here + · +66 │ fun test_inline_unpack() { + │ ^^^^^^^^^^^^^^^^^^ + +error: Invalid operation: access of the field `r` on type `M::T` can only be done within the defining module `0x42::M` + ┌─ tests/visibility-checker/resource_operator_inline.move:71:9 + │ +38 │ t.r + │ --- accessed here + · +71 │ fun test_inline_access() { + │ ^^^^^^^^^^^^^^^^^^ +72 │ let t = M::new_t(); +73 │ M::inline_access(t); + │ ------------------- from a call inlined at this callsite diff --git a/third_party/move/move-compiler-v2/tests/visibility-checker/resource_operator_inline.move b/third_party/move/move-compiler-v2/tests/visibility-checker/resource_operator_inline.move new file mode 100644 index 0000000000000..d134662164d37 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/visibility-checker/resource_operator_inline.move @@ -0,0 +1,77 @@ +address 0x42 { +module M { + struct R has key, store {} + struct T has key {r: R} + public fun new(): R { + R {} + } + + public fun new_t(): T { + T {r: R {}} + } + + public inline fun inline_borrow(addr: address): &R { + borrow_global(addr) + } + + public inline fun inline_borrow_mut(addr: address): &R { + borrow_global_mut(addr) + } + + public inline fun inline_move_to(account: &signer, r: R) { + move_to(account, r) + } + + public inline fun inline_move_from(addr: address): R { + move_from(addr) + } + + public inline fun inline_pack(): R { + R {} + } + + public inline fun inline_unpack(r: R) { + let R{} = r; + } + + public inline fun inline_access(t: T): R { + t.r + } + +} +module M2 { + use 0x42::M; + + fun test_borrow() { + M::inline_borrow(@0x42); + } + + fun test_borrow_mut() { + M::inline_borrow_mut(@0x42); + } + + fun test_move_to(account: signer) { + let r = M::new(); + M::inline_move_to(&account, r); + } + + fun test_move_from(addr: address) { + M::inline_move_from(addr); + } + + fun test_inline_pack() { + M::inline_pack(); + } + + fun test_inline_unpack() { + let r = M::new(); + M::inline_unpack(r); + } + + fun test_inline_access() { + let t = M::new_t(); + M::inline_access(t); + } + +} +} diff --git a/third_party/move/move-compiler-v2/tests/visibility-checker/resources_invalid.exp b/third_party/move/move-compiler-v2/tests/visibility-checker/resources_invalid.exp new file mode 100644 index 0000000000000..cfaeb36bfb3db --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/visibility-checker/resources_invalid.exp @@ -0,0 +1,12 @@ + +Diagnostics: +error: Invalid operation: access of the field `addr` on type `objects::ReaderRef` can only be done within the defining module `0x42::objects` + ┌─ tests/visibility-checker/resources_invalid.move:17:16 + │ + 8 │ borrow_global(ref.addr) + │ -------- accessed here + · +17 │ public fun get_value(ref: &obj::ReaderRef): u64 { + │ ^^^^^^^^^ +18 │ obj::reader(ref).val + │ ---------------- from a call inlined at this callsite diff --git a/third_party/move/move-compiler-v2/tests/visibility-checker/resources_invalid.move b/third_party/move/move-compiler-v2/tests/visibility-checker/resources_invalid.move new file mode 100644 index 0000000000000..3445aa71d15d9 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/visibility-checker/resources_invalid.move @@ -0,0 +1,20 @@ +module 0x42::objects { + + struct ReaderRef has store { + addr: address + } + + public inline fun reader(ref: &ReaderRef): &T { + borrow_global(ref.addr) + } +} + +module 0x42::token { + use 0x42::objects as obj; + + struct Token has key { val: u64 } + + public fun get_value(ref: &obj::ReaderRef): u64 { + obj::reader(ref).val + } +} diff --git a/third_party/move/move-compiler-v2/tests/visibility-checker/v1-typing/pack_private_with_field.exp b/third_party/move/move-compiler-v2/tests/visibility-checker/v1-typing/pack_private_with_field.exp new file mode 100644 index 0000000000000..061d00fe0df39 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/visibility-checker/v1-typing/pack_private_with_field.exp @@ -0,0 +1,15 @@ + +Diagnostics: +error: Invalid operation: pack of `m::S` can only be done within the defining module `0x42::m` + ┌─ tests/visibility-checker/v1-typing/pack_private_with_field.move:18:5 + │ +18 │ fun f() { + │ ^ +19 │ let s = S { + │ ╭───────────' +20 │ │ f1: 0, +21 │ │ f4: 0, +22 │ │ f2: 0, +23 │ │ f3: 0, +24 │ │ }; + │ ╰───' packed here diff --git a/third_party/move/move-compiler-v2/tests/visibility-checker/v1-typing/pack_private_with_field.move b/third_party/move/move-compiler-v2/tests/visibility-checker/v1-typing/pack_private_with_field.move new file mode 100644 index 0000000000000..fb46af0a1be8c --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/visibility-checker/v1-typing/pack_private_with_field.move @@ -0,0 +1,28 @@ +module 0x42::m { + +struct S { + f1: u64, + f2: u64, + f3: u64, + f4: u64, +} + +public fun consume(_: S) { abort 0 } + +} + +module 0x42::n { + +use 0x42::m::S; + +fun f() { + let s = S { + f1: 0, + f4: 0, + f2: 0, + f3: 0, + }; + 0x42::m::consume(s); +} + +} diff --git a/third_party/move/move-compiler-v2/tests/visibility-checker/v1-typing/pack_unpack_private.exp b/third_party/move/move-compiler-v2/tests/visibility-checker/v1-typing/pack_unpack_private.exp new file mode 100644 index 0000000000000..5ea76997dbaaf --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/visibility-checker/v1-typing/pack_unpack_private.exp @@ -0,0 +1,17 @@ + +Diagnostics: +error: Invalid operation: pack of `C::T` can only be done within the defining module `0x43::C` + ┌─ tests/visibility-checker/v1-typing/pack_unpack_private.move:7:16 + │ +7 │ public fun foo(): C::T { + │ ^^^ +8 │ C::T {} + │ ------- packed here + +error: Invalid operation: unpack of `C::T` can only be done within the defining module `0x43::C` + ┌─ tests/visibility-checker/v1-typing/pack_unpack_private.move:10:16 + │ +10 │ public fun bar(c: C::T) { + │ ^^^ +11 │ let C::T {} = c; + │ ------- unpacked here diff --git a/third_party/move/move-compiler-v2/tests/visibility-checker/v1-typing/pack_unpack_private.move b/third_party/move/move-compiler-v2/tests/visibility-checker/v1-typing/pack_unpack_private.move new file mode 100644 index 0000000000000..ecf581684f7d7 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/visibility-checker/v1-typing/pack_unpack_private.move @@ -0,0 +1,13 @@ +module 0x43::C { + struct T {} +} + +module 0x42::B { + use 0x43::C; + public fun foo(): C::T { + C::T {} + } + public fun bar(c: C::T) { + let C::T {} = c; + } +} diff --git a/third_party/move/move-compiler-v2/tests/visibility-checker/v1-typing/pack_unpack_private_script.exp b/third_party/move/move-compiler-v2/tests/visibility-checker/v1-typing/pack_unpack_private_script.exp new file mode 100644 index 0000000000000..1b3aa86df2648 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/visibility-checker/v1-typing/pack_unpack_private_script.exp @@ -0,0 +1,18 @@ + +Diagnostics: +error: Invalid operation: pack of `M::T` can only be done within the defining module `0x42::M` + ┌─ tests/visibility-checker/v1-typing/pack_unpack_private_script.move:11:9 + │ +11 │ fun main() { + │ ^^^^ +12 │ let t = T { }; + │ ------ packed here + +error: Invalid operation: unpack of `M::T` can only be done within the defining module `0x42::M` + ┌─ tests/visibility-checker/v1-typing/pack_unpack_private_script.move:11:9 + │ +11 │ fun main() { + │ ^^^^ +12 │ let t = T { }; +13 │ let T {} = t; + │ ---- unpacked here diff --git a/third_party/move/move-compiler-v2/tests/visibility-checker/v1-typing/pack_unpack_private_script.move b/third_party/move/move-compiler-v2/tests/visibility-checker/v1-typing/pack_unpack_private_script.move new file mode 100644 index 0000000000000..1aa3e3bae8137 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/visibility-checker/v1-typing/pack_unpack_private_script.move @@ -0,0 +1,15 @@ +module 0x42::M { + struct T {} + +} + + +script { + + use 0x42::M::T; + + fun main() { + let t = T { }; + let T {} = t; + } +} diff --git a/third_party/move/move-compiler-v2/tools/testdiff/src/main.rs b/third_party/move/move-compiler-v2/tools/testdiff/src/main.rs index 4829b9ce2c04c..486e411f13087 100644 --- a/third_party/move/move-compiler-v2/tools/testdiff/src/main.rs +++ b/third_party/move/move-compiler-v2/tools/testdiff/src/main.rs @@ -115,6 +115,10 @@ static UNIT_PATH_REMAP: Lazy> = Lazy::new(|| { "acquires-checker/v1-tests".to_string(), "typing".to_string(), ); + map.insert( + "checking-lang-v1/v1-typing".to_string(), + "typing".to_string(), + ); map }); From 462ec0b4473deef5b0ea36b4f1f04ebb5b66fd9a Mon Sep 17 00:00:00 2001 From: WGB5445 <919603023@qq.com> Date: Thu, 11 Apr 2024 07:45:58 +0800 Subject: [PATCH 36/36] [Compiler][VM] Fix compilation error for view function: View function should not have signer parameters (#12529) * feat: Fix view function signer paremter * feat: update error message * fmt * fmt * feat: Add view fun e2e test * feat: remove view function verifier * feat: fix test --------- Co-authored-by: runtianz --- .../e2e-move-tests/src/tests/attributes.rs | 60 +++++++++++++++++++ aptos-move/framework/src/extended_checks.rs | 25 ++++++++ 2 files changed, 85 insertions(+) diff --git a/aptos-move/e2e-move-tests/src/tests/attributes.rs b/aptos-move/e2e-move-tests/src/tests/attributes.rs index 13f4f8727baf0..13d58501efa95 100644 --- a/aptos-move/e2e-move-tests/src/tests/attributes.rs +++ b/aptos-move/e2e-move-tests/src/tests/attributes.rs @@ -30,6 +30,66 @@ fn test_view_attribute() { assert_success!(h.publish_package(&account, path.path())); } +#[test] +#[should_panic] +fn test_view_attribute_with_signer() { + let mut h = MoveHarness::new(); + let account = h.new_account_at(AccountAddress::from_hex_literal("0xf00d").unwrap()); + + let mut builder = PackageBuilder::new("Package"); + builder.add_source( + "m.move", + r#" + module 0xf00d::M { + #[view] + fun view(_:signer,value: u64): u64 { value } + } + "#, + ); + let path = builder.write_to_temp().unwrap(); + h.create_publish_package(&account, path.path(), None, |_| {}); +} + +#[test] +#[should_panic] +fn test_view_attribute_with_ref_signer() { + let mut h = MoveHarness::new(); + let account = h.new_account_at(AccountAddress::from_hex_literal("0xf00d").unwrap()); + + let mut builder = PackageBuilder::new("Package"); + builder.add_source( + "m.move", + r#" + module 0xf00d::M { + #[view] + fun view(_:&signer,value: u64): u64 { value } + } + "#, + ); + let path = builder.write_to_temp().unwrap(); + h.create_publish_package(&account, path.path(), None, |_| {}); +} + +#[test] +#[should_panic] +fn test_view_attribute_with_mut_ref_signer() { + let mut h = MoveHarness::new(); + let account = h.new_account_at(AccountAddress::from_hex_literal("0xf00d").unwrap()); + + let mut builder = PackageBuilder::new("Package"); + builder.add_source( + "m.move", + r#" + module 0xf00d::M { + #[view] + fun view(_:&mut signer,value: u64): u64 { value } + } + "#, + ); + let path = builder.write_to_temp().unwrap(); + h.create_publish_package(&account, path.path(), None, |_| {}); +} + #[test] #[should_panic] fn test_view_attribute_on_non_view() { diff --git a/aptos-move/framework/src/extended_checks.rs b/aptos-move/framework/src/extended_checks.rs index 01472f20c795b..5674208bb847e 100644 --- a/aptos-move/framework/src/extended_checks.rs +++ b/aptos-move/framework/src/extended_checks.rs @@ -498,6 +498,31 @@ impl<'a> ExtendedChecker<'a> { self.env .error(&fun.get_id_loc(), "view function must return values") } + + fun.get_parameter_types() + .iter() + .for_each(|parameter_type| match parameter_type { + Type::Primitive(inner) => { + if inner == &PrimitiveType::Signer { + self.env.error( + &fun.get_id_loc(), + "view function cannot use the signer paremter", + ) + } + }, + Type::Reference(_, inner) => { + if let Type::Primitive(inner) = inner.as_ref() { + if inner == &PrimitiveType::Signer { + self.env.error( + &fun.get_id_loc(), + "view function cannot use the & signer paremter", + ) + } + } + }, + _ => (), + }); + // Remember the runtime info that this is a view function let module_id = self.get_runtime_module_id(module); self.output