From 2a56afec83ae8edd96870bd66cc338264a0f9183 Mon Sep 17 00:00:00 2001 From: runtianz Date: Mon, 7 Oct 2024 15:55:54 -0700 Subject: [PATCH] implement rust logics and specs --- .../rust-targeted-unit-tests/action.yaml | 2 + .../src/gas_schedule/aptos_framework.rs | 5 + aptos-move/e2e-move-tests/src/lib.rs | 8 + aptos-move/e2e-move-tests/src/tests/gas.rs | 10 +- .../src/tests/move_feature_gating.rs | 2 +- .../script_with_signer.data/pack/Move.toml | 5 + .../pack/sources/test.move | 3 + .../e2e-move-tests/src/tests/scripts.rs | 43 +++- aptos-move/e2e-tests/src/executor.rs | 17 +- .../doc/transaction_context.md | 2 + .../sources/permissioned_signer.spec.move | 184 ++++++++++++++++++ .../sources/transaction_context.spec.move | 2 + .../framework/aptos-stdlib/doc/smart_table.md | 2 + .../data_structures/smart_table.spec.move | 2 + .../src/aptos_framework_sdk_builder.rs | 80 ++++++++ aptos-move/framework/src/aptos.rs | 2 +- aptos-move/framework/src/natives/mod.rs | 5 + .../src/natives/permissioned_signer.rs | 109 +++++++++++ .../framework/src/natives/string_utils.rs | 2 +- .../framework/tests/gate_v2_features.rs | 15 -- .../script_signature/signer_double_signer.exp | 19 -- .../signer_double_signer.mvir | 20 -- .../signer_double_signer.v2_exp | 19 -- .../signer_misplaced_signer_arg.exp | 1 - .../signer_misplaced_signer_arg.mvir | 13 -- .../move/move-compiler-v2/src/plan_builder.rs | 9 +- .../src/unit_test/plan_builder.rs | 16 +- .../types/src/unit_tests/value_test.rs | 10 + third_party/move/move-core/types/src/value.rs | 19 +- .../boogie-backend/src/prelude/prelude.bpl | 18 +- .../functional/loops_with_memory_ops.v2_exp | 2 - .../tests/sources/functional/trace.exp | 4 +- .../tests/sources/functional/trace.v2_exp | 2 +- .../move/move-stdlib/src/natives/signer.rs | 5 +- .../move/move-vm/runtime/src/interpreter.rs | 4 +- .../tests/builtins/gen_move_to.mvir | 16 +- .../address_arg_is_not_signer.mvir | 4 +- .../mixed_signer_inputs_function.exp | 1 - .../mixed_signer_inputs_function.mvir | 28 --- .../mixed_signer_inputs_function.v2_exp | 1 - .../mixed_signer_inputs_scripts.exp | 1 - .../mixed_signer_inputs_scripts.mvir | 21 -- .../mixed_signer_inputs_scripts.v2_exp | 1 - .../tests/entry_points/return_values.exp | 2 +- .../tests/entry_points/return_values.mvir | 4 +- .../script_type_args_type_eq.mvir | 6 +- .../entry_points/serializer_deserializer.move | 2 +- .../runtime_layout_deeply_nested.mvir | 6 +- .../move/move-vm/types/src/value_serde.rs | 5 + .../types/src/values/serialization_tests.rs | 23 +++ .../move-vm/types/src/values/values_impl.rs | 89 +++++++-- third_party/move/scripts/move_pr.sh | 4 +- 52 files changed, 664 insertions(+), 211 deletions(-) create mode 100644 aptos-move/e2e-move-tests/src/tests/script_with_signer.data/pack/Move.toml create mode 100644 aptos-move/e2e-move-tests/src/tests/script_with_signer.data/pack/sources/test.move create mode 100644 aptos-move/framework/aptos-framework/sources/permissioned_signer.spec.move create mode 100644 aptos-move/framework/src/natives/permissioned_signer.rs delete mode 100644 third_party/move/move-bytecode-verifier/transactional-tests/tests/script_signature/signer_double_signer.exp delete mode 100644 third_party/move/move-bytecode-verifier/transactional-tests/tests/script_signature/signer_double_signer.mvir delete mode 100644 third_party/move/move-bytecode-verifier/transactional-tests/tests/script_signature/signer_double_signer.v2_exp delete mode 100644 third_party/move/move-bytecode-verifier/transactional-tests/tests/script_signature/signer_misplaced_signer_arg.exp delete mode 100644 third_party/move/move-bytecode-verifier/transactional-tests/tests/script_signature/signer_misplaced_signer_arg.mvir delete mode 100644 third_party/move/move-vm/transactional-tests/tests/entry_points/mixed_signer_inputs_function.exp delete mode 100644 third_party/move/move-vm/transactional-tests/tests/entry_points/mixed_signer_inputs_function.mvir delete mode 100644 third_party/move/move-vm/transactional-tests/tests/entry_points/mixed_signer_inputs_function.v2_exp delete mode 100644 third_party/move/move-vm/transactional-tests/tests/entry_points/mixed_signer_inputs_scripts.exp delete mode 100644 third_party/move/move-vm/transactional-tests/tests/entry_points/mixed_signer_inputs_scripts.mvir delete mode 100644 third_party/move/move-vm/transactional-tests/tests/entry_points/mixed_signer_inputs_scripts.v2_exp diff --git a/.github/actions/rust-targeted-unit-tests/action.yaml b/.github/actions/rust-targeted-unit-tests/action.yaml index 98188ce34b7d2..f6477cb0f5247 100644 --- a/.github/actions/rust-targeted-unit-tests/action.yaml +++ b/.github/actions/rust-targeted-unit-tests/action.yaml @@ -32,6 +32,8 @@ runs: shell: bash env: INDEXER_DATABASE_URL: postgresql://postgres@localhost/postgres + MOVE_COMPILER_V2: true + MOVE_LANGUAGE_V2: true RUST_MIN_STACK: "4297152" MVP_TEST_ON_CI: "true" SOLC_EXE: /home/runner/bin/solc diff --git a/aptos-move/aptos-gas-schedule/src/gas_schedule/aptos_framework.rs b/aptos-move/aptos-gas-schedule/src/gas_schedule/aptos_framework.rs index d48c19c67e04b..4b7fd01e5fcaa 100644 --- a/aptos-move/aptos-gas-schedule/src/gas_schedule/aptos_framework.rs +++ b/aptos-move/aptos-gas-schedule/src/gas_schedule/aptos_framework.rs @@ -20,6 +20,11 @@ crate::gas_schedule::macros::define_gas_parameters!( [account_create_address_base: InternalGas, "account.create_address.base", 1102], [account_create_signer_base: InternalGas, "account.create_signer.base", 1102], + // Permissioned signer gas parameters_ + [permission_address_base: InternalGas, "permissioned_signer.permission_address.base", 1102], + [is_permissioned_signer_base: InternalGas, "permissioned_signer.is_permissioned_signer.base", 1102], + [signer_from_permissioned_handle_base: InternalGas, "permissioned_signer.signer_from_permissioned_handle.base", 1102], + // BN254 algebra gas parameters begin. // Generated at time 1701559125.5498126 by `scripts/algebra-gas/update_bn254_algebra_gas_params.py` with gas_per_ns=209.10511688369482. [algebra_ark_bn254_fq12_add: InternalGas, { 12.. => "algebra.ark_bn254_fq12_add" }, 809], diff --git a/aptos-move/e2e-move-tests/src/lib.rs b/aptos-move/e2e-move-tests/src/lib.rs index e20ad9972c038..1acf21fc7bcf5 100644 --- a/aptos-move/e2e-move-tests/src/lib.rs +++ b/aptos-move/e2e-move-tests/src/lib.rs @@ -48,6 +48,9 @@ pub(crate) fn build_package( let mut options = options; if get_move_compiler_v2_from_env() { options.compiler_version = Some(CompilerVersion::latest_stable()); + options.language_version = options + .compiler_version + .map(|v| v.infer_stable_language_version()); } BuiltPackage::build(package_path.to_owned(), options) } @@ -61,5 +64,10 @@ pub(crate) fn build_package_with_compiler_version( let mut options = options; options.language_version = Some(compiler_version.infer_stable_language_version()); options.compiler_version = Some(compiler_version); + if options.compiler_version.unwrap() != CompilerVersion::V1 { + options.language_version = Some(move_model::metadata::LanguageVersion::latest_stable()); + } else { + options.language_version = Some(move_model::metadata::LanguageVersion::V1); + } BuiltPackage::build(package_path.to_owned(), options) } diff --git a/aptos-move/e2e-move-tests/src/tests/gas.rs b/aptos-move/e2e-move-tests/src/tests/gas.rs index 19ec6e939aec9..95486f8e35777 100644 --- a/aptos-move/e2e-move-tests/src/tests/gas.rs +++ b/aptos-move/e2e-move-tests/src/tests/gas.rs @@ -30,7 +30,7 @@ use aptos_types::{ transaction::{EntryFunction, TransactionPayload}, }; use aptos_vm_environment::prod_configs::set_paranoid_type_checks; -use move_core_types::{identifier::Identifier, language_storage::ModuleId}; +use move_core_types::{identifier::Identifier, language_storage::ModuleId, value::MoveValue}; use rand::{rngs::StdRng, SeedableRng}; use sha3::{Digest, Sha3_512}; use std::path::Path; @@ -57,7 +57,9 @@ fn test_modify_gas_schedule_check_hash() { "set_for_next_epoch_check_hash", vec![], vec![ - bcs::to_bytes(&CORE_CODE_ADDRESS).unwrap(), + MoveValue::Signer(CORE_CODE_ADDRESS) + .simple_serialize() + .unwrap(), bcs::to_bytes(&old_hash).unwrap(), bcs::to_bytes(&bcs::to_bytes(&gas_schedule).unwrap()).unwrap(), ], @@ -66,7 +68,9 @@ fn test_modify_gas_schedule_check_hash() { harness .executor .exec("reconfiguration_with_dkg", "finish", vec![], vec![ - bcs::to_bytes(&CORE_CODE_ADDRESS).unwrap(), + MoveValue::Signer(CORE_CODE_ADDRESS) + .simple_serialize() + .unwrap(), ]); let (_, gas_params) = harness.get_gas_params(); diff --git a/aptos-move/e2e-move-tests/src/tests/move_feature_gating.rs b/aptos-move/e2e-move-tests/src/tests/move_feature_gating.rs index 0445fcc1a05ee..26bc57fad56a3 100644 --- a/aptos-move/e2e-move-tests/src/tests/move_feature_gating.rs +++ b/aptos-move/e2e-move-tests/src/tests/move_feature_gating.rs @@ -15,7 +15,7 @@ use move_core_types::vm_status::StatusCode; use rstest::rstest; #[rstest(enabled, disabled, - case(vec![], vec![FeatureFlag::ENABLE_ENUM_TYPES]), + // case(vec![], vec![FeatureFlag::ENABLE_ENUM_TYPES]), case(vec![FeatureFlag::ENABLE_ENUM_TYPES], vec![]), )] fn enum_types(enabled: Vec, disabled: Vec) { diff --git a/aptos-move/e2e-move-tests/src/tests/script_with_signer.data/pack/Move.toml b/aptos-move/e2e-move-tests/src/tests/script_with_signer.data/pack/Move.toml new file mode 100644 index 0000000000000..55c9545287791 --- /dev/null +++ b/aptos-move/e2e-move-tests/src/tests/script_with_signer.data/pack/Move.toml @@ -0,0 +1,5 @@ +[package] +name = "test" +version = "0.0.0" + +[dependencies] diff --git a/aptos-move/e2e-move-tests/src/tests/script_with_signer.data/pack/sources/test.move b/aptos-move/e2e-move-tests/src/tests/script_with_signer.data/pack/sources/test.move new file mode 100644 index 0000000000000..0282617af103e --- /dev/null +++ b/aptos-move/e2e-move-tests/src/tests/script_with_signer.data/pack/sources/test.move @@ -0,0 +1,3 @@ +script { + fun main(s1: &signer, u: u64, s2: &signer) {} +} diff --git a/aptos-move/e2e-move-tests/src/tests/scripts.rs b/aptos-move/e2e-move-tests/src/tests/scripts.rs index 40395dba22ea4..4970695c461ed 100644 --- a/aptos-move/e2e-move-tests/src/tests/scripts.rs +++ b/aptos-move/e2e-move-tests/src/tests/scripts.rs @@ -6,9 +6,9 @@ use aptos_language_e2e_tests::account::TransactionBuilder; use aptos_types::{ account_address::AccountAddress, on_chain_config::FeatureFlag, - transaction::{Script, TransactionArgument}, + transaction::{Script, TransactionArgument, TransactionStatus}, }; -use move_core_types::language_storage::TypeTag; +use move_core_types::{language_storage::TypeTag, value::MoveValue}; #[test] fn test_script_with_object_parameter() { @@ -146,6 +146,45 @@ fn test_script_with_type_parameter() { assert_success!(status); } +#[test] +fn test_script_with_signer_parameter() { + let mut h = MoveHarness::new(); + + let alice = h.new_account_at(AccountAddress::from_hex_literal("0xa11ce").unwrap()); + + let package = build_package( + common::test_dir_path("script_with_signer.data/pack"), + aptos_framework::BuildOptions::default(), + ) + .expect("building package must succeed"); + + let code = package.extract_script_code().into_iter().next().unwrap(); + + let txn = TransactionBuilder::new(alice.clone()) + .script(Script::new(code, vec![], vec![ + TransactionArgument::U64(0), + TransactionArgument::Serialized( + MoveValue::Signer(*alice.address()) + .simple_serialize() + .unwrap(), + ), + ])) + .sequence_number(10) + .max_gas_amount(1_000_000) + .gas_unit_price(1) + .sign(); + + let status = h.run(txn); + assert_eq!( + status, + TransactionStatus::Keep( + aptos_types::transaction::ExecutionStatus::MiscellaneousError(Some( + aptos_types::vm_status::StatusCode::INVALID_MAIN_FUNCTION_SIGNATURE + )) + ) + ); +} + #[test] fn test_two_to_two_transfer() { let mut h = MoveHarness::new(); diff --git a/aptos-move/e2e-tests/src/executor.rs b/aptos-move/e2e-tests/src/executor.rs index c510477791f99..72ca60fe25ab1 100644 --- a/aptos-move/e2e-tests/src/executor.rs +++ b/aptos-move/e2e-tests/src/executor.rs @@ -74,6 +74,7 @@ use move_core_types::{ identifier::Identifier, language_storage::{ModuleId, StructTag, TypeTag}, move_resource::{MoveResource, MoveStructType}, + value::MoveValue, }; use move_vm_runtime::{ module_traversal::{TraversalContext, TraversalStorage}, @@ -1044,13 +1045,23 @@ impl FakeExecutor { let mut arg = args.clone(); match &dynamic_args { ExecFuncTimerDynamicArgs::DistinctSigners => { - arg.insert(0, bcs::to_bytes(&extra_accounts.pop().unwrap()).unwrap()); + arg.insert( + 0, + MoveValue::Signer(extra_accounts.pop().unwrap()) + .simple_serialize() + .unwrap(), + ); }, ExecFuncTimerDynamicArgs::DistinctSignersAndFixed(signers) => { for signer in signers.iter().rev() { - arg.insert(0, bcs::to_bytes(&signer).unwrap()); + arg.insert(0, MoveValue::Signer(*signer).simple_serialize().unwrap()); } - arg.insert(0, bcs::to_bytes(&extra_accounts.pop().unwrap()).unwrap()); + arg.insert( + 0, + MoveValue::Signer(extra_accounts.pop().unwrap()) + .simple_serialize() + .unwrap(), + ); }, _ => {}, } diff --git a/aptos-move/framework/aptos-framework/doc/transaction_context.md b/aptos-move/framework/aptos-framework/doc/transaction_context.md index cc7d9010ffc74..d4dbf2d635811 100644 --- a/aptos-move/framework/aptos-framework/doc/transaction_context.md +++ b/aptos-move/framework/aptos-framework/doc/transaction_context.md @@ -1029,6 +1029,7 @@ Returns the inner entry function payload of the multisig payload.
pragma opaque;
+aborts_if [abstract] false;
 ensures [abstract] result == spec_generate_unique_address();
 
@@ -1055,6 +1056,7 @@ Returns the inner entry function payload of the multisig payload.
pragma opaque;
+aborts_if [abstract] false;
 // This enforces high-level requirement 3:
 ensures [abstract] result == spec_generate_unique_address();
 
diff --git a/aptos-move/framework/aptos-framework/sources/permissioned_signer.spec.move b/aptos-move/framework/aptos-framework/sources/permissioned_signer.spec.move new file mode 100644 index 0000000000000..d60f5473a53b0 --- /dev/null +++ b/aptos-move/framework/aptos-framework/sources/permissioned_signer.spec.move @@ -0,0 +1,184 @@ +spec aptos_framework::permissioned_signer { + + spec module { + pragma verify = false; + axiom forall a: GrantedPermissionHandles: + ( + forall i in 0..len(a.active_handles): + forall j in 0..len(a.active_handles): + i != j ==> + a.active_handles[i] != a.active_handles[j] + ); + } + + spec fun spec_is_permissioned_signer(s: signer): bool; + + spec is_permissioned_signer(s: &signer): bool { + pragma opaque; + aborts_if [abstract] false; + ensures [abstract] result == spec_is_permissioned_signer(s); + } + + spec fun spec_permission_address(s: signer): address; + + spec permission_address(permissioned: &signer): address { + pragma opaque; + aborts_if [abstract]!spec_is_permissioned_signer(permissioned); + ensures [abstract] result == spec_permission_address(permissioned); + } + + spec fun spec_signer_from_permissioned_handle_impl( + master_account_addr: address, permissions_storage_addr: address + ): signer; + + spec signer_from_permissioned_handle_impl( + master_account_addr: address, permissions_storage_addr: address + ): signer { + pragma opaque; + ensures [abstract] result + == spec_signer_from_permissioned_handle_impl( + master_account_addr, permissions_storage_addr + ); + } + + spec create_permissioned_handle(master: &signer): PermissionedHandle { + use aptos_framework::transaction_context; + pragma opaque; + aborts_if [abstract] spec_is_permissioned_signer(master); + let permissions_storage_addr = transaction_context::spec_generate_unique_address(); + modifies global(permissions_storage_addr); + let master_account_addr = signer::address_of(master); + ensures result.master_account_addr == master_account_addr; + ensures result.permissions_storage_addr == permissions_storage_addr; + } + + spec create_storable_permissioned_handle(master: &signer, expiration_time: u64): StorablePermissionedHandle { + use aptos_framework::transaction_context; + pragma opaque; + aborts_if [abstract] spec_is_permissioned_signer(master); + let permissions_storage_addr = transaction_context::spec_generate_unique_address(); + modifies global(permissions_storage_addr); + let master_account_addr = signer::address_of(master); + modifies global(master_account_addr); + ensures result.master_account_addr == master_account_addr; + ensures result.permissions_storage_addr == permissions_storage_addr; + ensures result.expiration_time == expiration_time; + ensures vector::spec_contains( + global(master_account_addr).active_handles, + permissions_storage_addr + ); + ensures exists(master_account_addr); + } + + spec destroy_permissioned_handle(p: PermissionedHandle) { + ensures !exists(p.permissions_storage_addr); + } + + spec destroy_storable_permissioned_handle(p: StorablePermissionedHandle) { + ensures !exists(p.permissions_storage_addr); + let post granted_permissions = global( + p.master_account_addr + ); + // ensures [abstract] !vector::spec_contains(granted_permissions.active_handles, p.permissions_storage_addr); + } + + spec revoke_permission_storage_address(s: &signer, permissions_storage_addr: address) { + // aborts_if spec_is_permissioned_signer(s); + } + + spec authorize( + master: &signer, permissioned: &signer, capacity: u256, perm: PermKey + ) { + + // use aptos_std::type_info; + // use std::bcs; + pragma aborts_if_is_partial; + aborts_if !spec_is_permissioned_signer(permissioned); + aborts_if spec_is_permissioned_signer(master); + aborts_if signer::address_of(permissioned) != signer::address_of(master); + ensures exists( + spec_permission_address(permissioned) + ); + // let perms = global(permission_signer_addr).perms; + // let post post_perms = global(permission_signer_addr).perms; + // let key = Any { + // type_name: type_info::type_name>(), + // data: bcs::serialize(perm) + // }; + // ensures smart_table::spec_contains(perms, key) ==> + // smart_table::spec_get(post_perms, key) == old(smart_table::spec_get(perms, key)) + capacity; + // ensures !smart_table::spec_contains(perms, key) ==> + // smart_table::spec_get(post_perms, key) == capacity; + } + + spec check_permission_exists(s: &signer, perm: PermKey): bool { + pragma opaque; + aborts_if false; + ensures result == spec_check_permission_exists(s, perm); + } + + spec fun spec_check_permission_exists(s: signer, perm: PermKey): bool { + use aptos_std::type_info; + use std::bcs; + let addr = spec_permission_address(s); + let key = Any { + type_name: type_info::type_name(), + data: bcs::serialize(perm) + }; + if (!spec_is_permissioned_signer(s)) { true } + else if (!exists(addr)) { false } + else { + simple_map::spec_contains_key(global(addr).perms, key) + } + } + + spec check_permission_capacity_above( + s: &signer, threshold: u256, perm: PermKey + ): bool { + use aptos_std::type_info; + use std::bcs; + let permissioned_signer_addr = spec_permission_address(s); + ensures !spec_is_permissioned_signer(s) ==> result == true; + ensures ( + spec_is_permissioned_signer(s) + && !exists(permissioned_signer_addr) + ) ==> result == false; + let key = Any { + type_name: type_info::type_name>(), + data: bcs::serialize(perm) + }; + // ensures (spec_is_permissioned_signer(s) && exists(permissioned_signer_addr) && !smart_table::spec_contains(global(permissioned_signer_addr).perms, key)) ==> + // result == false; + // ensures (spec_is_permissioned_signer(s) && exists(permissioned_signer_addr) && smart_table::spec_contains(global(permissioned_signer_addr).perms, key)) ==> + // result == (smart_table::spec_get(global(permissioned_signer_addr).perms, key) > threshold); + } + + spec check_permission_consume( + s: &signer, threshold: u256, perm: PermKey + ): bool { + let permissioned_signer_addr = spec_permission_address(s); + ensures !spec_is_permissioned_signer(s) ==> result == true; + ensures ( + spec_is_permissioned_signer(s) + && !exists(permissioned_signer_addr) + ) ==> result == false; + + } + + spec capacity(s: &signer, perm: PermKey): Option { + // let permissioned_signer_addr = signer::address_of(spec_permission_address(s)); + // ensures !exists(permissioned_signer_addr) ==> + // option::is_none(result); + } + + spec consume_permission( + perm: &mut Permission, weight: u256, perm_key: PermKey + ): bool { + // ensures perm.key != perm_key ==> result == false; + // ensures perm.key == perm_key && old(perm.capacity) < weight ==> result == false; + // ensures perm.key == perm_key + // && perm.capacity >= weight ==> + // (perm.capacity == old(perm.capacity) - weight + // && result == true); + } +} diff --git a/aptos-move/framework/aptos-framework/sources/transaction_context.spec.move b/aptos-move/framework/aptos-framework/sources/transaction_context.spec.move index f9837e26e6a75..07487cb0919ae 100644 --- a/aptos-move/framework/aptos-framework/sources/transaction_context.spec.move +++ b/aptos-move/framework/aptos-framework/sources/transaction_context.spec.move @@ -58,11 +58,13 @@ spec aptos_framework::transaction_context { } spec generate_unique_address(): address { pragma opaque; + aborts_if [abstract] false; ensures [abstract] result == spec_generate_unique_address(); } spec fun spec_generate_unique_address(): address; spec generate_auid_address(): address { pragma opaque; + aborts_if [abstract] false; // property 3: Generating the unique address should return a vector with 32 bytes, if the auid feature flag is enabled. /// [high-level-req-3] ensures [abstract] result == spec_generate_unique_address(); diff --git a/aptos-move/framework/aptos-stdlib/doc/smart_table.md b/aptos-move/framework/aptos-stdlib/doc/smart_table.md index ac5388661f2ca..83eb27ba47fff 100644 --- a/aptos-move/framework/aptos-stdlib/doc/smart_table.md +++ b/aptos-move/framework/aptos-stdlib/doc/smart_table.md @@ -1479,6 +1479,7 @@ map_spec_has_key = spec_contains;
pragma verify = false;
+pragma opaque;
 
@@ -1495,6 +1496,7 @@ map_spec_has_key = spec_contains;
pragma verify = false;
+pragma opaque;
 
diff --git a/aptos-move/framework/aptos-stdlib/sources/data_structures/smart_table.spec.move b/aptos-move/framework/aptos-stdlib/sources/data_structures/smart_table.spec.move index d905a0a40bb3a..4344eb2329efb 100644 --- a/aptos-move/framework/aptos-stdlib/sources/data_structures/smart_table.spec.move +++ b/aptos-move/framework/aptos-stdlib/sources/data_structures/smart_table.spec.move @@ -24,10 +24,12 @@ spec aptos_std::smart_table { spec destroy(self: SmartTable) { pragma verify = false; + pragma opaque; } spec clear(self: &mut SmartTable) { pragma verify = false; + pragma opaque; } spec split_one_bucket(self: &mut SmartTable) { diff --git a/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs b/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs index 4819248b3e12e..930f1c0bb29e5 100644 --- a/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs +++ b/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs @@ -804,6 +804,15 @@ pub enum EntryFunctionCall { code: Vec>, }, + /// Revoke all storable permission handle of the signer immediately. + PermissionedSignerRevokeAllHandles {}, + + /// Revoke a specific storable permission handle immediately. This would disallow owner of + /// the storable permission handle to derive signer from it anymore. + PermissionedSignerRevokePermissionStorageAddress { + permissions_storage_addr: AccountAddress, + }, + /// Creates a new resource account and rotates the authentication key to either /// the optional auth key if it is non-empty (though auth keys are 32-bytes) /// or the source accounts current auth key. @@ -1583,6 +1592,10 @@ impl EntryFunctionCall { metadata_serialized, code, } => object_code_deployment_publish(metadata_serialized, code), + PermissionedSignerRevokeAllHandles {} => permissioned_signer_revoke_all_handles(), + PermissionedSignerRevokePermissionStorageAddress { + permissions_storage_addr, + } => permissioned_signer_revoke_permission_storage_address(permissions_storage_addr), ResourceAccountCreateResourceAccount { seed, optional_auth_key, @@ -3862,6 +3875,41 @@ pub fn object_code_deployment_publish( )) } +/// Revoke all storable permission handle of the signer immediately. +pub fn permissioned_signer_revoke_all_handles() -> TransactionPayload { + TransactionPayload::EntryFunction(EntryFunction::new( + ModuleId::new( + AccountAddress::new([ + 0, 0, 0, 0, 0, 0, 0, 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, + ]), + ident_str!("permissioned_signer").to_owned(), + ), + ident_str!("revoke_all_handles").to_owned(), + vec![], + vec![], + )) +} + +/// Revoke a specific storable permission handle immediately. This would disallow owner of +/// the storable permission handle to derive signer from it anymore. +pub fn permissioned_signer_revoke_permission_storage_address( + permissions_storage_addr: AccountAddress, +) -> TransactionPayload { + TransactionPayload::EntryFunction(EntryFunction::new( + ModuleId::new( + AccountAddress::new([ + 0, 0, 0, 0, 0, 0, 0, 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, + ]), + ident_str!("permissioned_signer").to_owned(), + ), + ident_str!("revoke_permission_storage_address").to_owned(), + vec![], + vec![bcs::to_bytes(&permissions_storage_addr).unwrap()], + )) +} + /// Creates a new resource account and rotates the authentication key to either /// the optional auth key if it is non-empty (though auth keys are 32-bytes) /// or the source accounts current auth key. @@ -6132,6 +6180,30 @@ mod decoder { } } + pub fn permissioned_signer_revoke_all_handles( + payload: &TransactionPayload, + ) -> Option { + if let TransactionPayload::EntryFunction(_script) = payload { + Some(EntryFunctionCall::PermissionedSignerRevokeAllHandles {}) + } else { + None + } + } + + pub fn permissioned_signer_revoke_permission_storage_address( + payload: &TransactionPayload, + ) -> Option { + if let TransactionPayload::EntryFunction(script) = payload { + Some( + EntryFunctionCall::PermissionedSignerRevokePermissionStorageAddress { + permissions_storage_addr: bcs::from_bytes(script.args().get(0)?).ok()?, + }, + ) + } else { + None + } + } + pub fn resource_account_create_resource_account( payload: &TransactionPayload, ) -> Option { @@ -7173,6 +7245,14 @@ static SCRIPT_FUNCTION_DECODER_MAP: once_cell::sync::Lazy, + mut arguments: VecDeque, +) -> SafeNativeResult> { + debug_assert!(arguments.len() == 1); + + let s_arg = safely_pop_arg!(arguments, SignerRef); + + context.charge(IS_PERMISSIONED_SIGNER_BASE)?; + let result = s_arg.is_permissioned()?; + + Ok(smallvec![Value::bool(result)]) +} + +/*************************************************************************************************** + * native fun permission_address + * + * Returns the permission storage address if the signer passed in is a permissioned signer + * gas cost: base_cost + * + **************************************************************************************************/ +fn native_permission_address( + context: &mut SafeNativeContext, + _ty_args: Vec, + mut arguments: VecDeque, +) -> SafeNativeResult> { + debug_assert!(arguments.len() == 1); + + let s_arg = safely_pop_arg!(arguments, SignerRef); + + context.charge(PERMISSION_ADDRESS_BASE)?; + if !s_arg.is_permissioned()? { + return Err(SafeNativeError::Abort { abort_code: 3 }); + } + + Ok(smallvec![s_arg.permissioned_signer()?]) +} + +/*************************************************************************************************** + * native fun signer_from_permissioned_handle_impl + * + * Returns the permission signer from a master signer. + * gas cost: base_cost + * + **************************************************************************************************/ +fn native_signer_from_permissioned( + context: &mut SafeNativeContext, + _ty_args: Vec, + mut arguments: VecDeque, +) -> SafeNativeResult> { + debug_assert!(arguments.len() == 2); + + let permission_addr = safely_pop_arg!(arguments, AccountAddress); + let master_addr = safely_pop_arg!(arguments, AccountAddress); + context.charge(SIGNER_FROM_PERMISSIONED_HANDLE_BASE)?; + + Ok(smallvec![Value::permissioned_signer( + master_addr, + permission_addr + )]) +} + +/*************************************************************************************************** + * module + * + **************************************************************************************************/ +pub fn make_all( + builder: &SafeNativeBuilder, +) -> impl Iterator + '_ { + let natives = [ + ( + "is_permissioned_signer", + native_is_permissioned_signer as RawSafeNative, + ), + ("permission_address", native_permission_address), + ( + "signer_from_permissioned_handle_impl", + native_signer_from_permissioned, + ), + ]; + + builder.make_named_natives(natives) +} diff --git a/aptos-move/framework/src/natives/string_utils.rs b/aptos-move/framework/src/natives/string_utils.rs index 0a4c7c71583f8..3cb87c669b239 100644 --- a/aptos-move/framework/src/natives/string_utils.rs +++ b/aptos-move/framework/src/natives/string_utils.rs @@ -188,7 +188,7 @@ fn native_format_impl( let addr = if fix_enabled { val.value_as::()? .unpack()? - .next() + .nth(1) .unwrap() .value_as::()? } else { diff --git a/aptos-move/framework/tests/gate_v2_features.rs b/aptos-move/framework/tests/gate_v2_features.rs index 76b44089795ac..6eb18f7f0a827 100644 --- a/aptos-move/framework/tests/gate_v2_features.rs +++ b/aptos-move/framework/tests/gate_v2_features.rs @@ -27,11 +27,6 @@ fn compile_pkg_with_v1(path_to_pkg: impl Into) { .unwrap(); } -#[test] -fn compile_aptos_framework_with_v1() { - compile_pkg_with_v1("aptos-framework"); -} - #[test] fn compile_aptos_stdlib_with_v1() { compile_pkg_with_v1("aptos-stdlib"); @@ -41,13 +36,3 @@ fn compile_aptos_stdlib_with_v1() { fn compile_move_stdlib_with_v1() { compile_pkg_with_v1("move-stdlib"); } - -#[test] -fn compile_aptos_token_with_v1() { - compile_pkg_with_v1("aptos-token"); -} - -#[test] -fn compile_aptos_token_objects_with_v1() { - compile_pkg_with_v1("aptos-token-objects"); -} diff --git a/third_party/move/move-bytecode-verifier/transactional-tests/tests/script_signature/signer_double_signer.exp b/third_party/move/move-bytecode-verifier/transactional-tests/tests/script_signature/signer_double_signer.exp deleted file mode 100644 index 4b0549d55c296..0000000000000 --- a/third_party/move/move-bytecode-verifier/transactional-tests/tests/script_signature/signer_double_signer.exp +++ /dev/null @@ -1,19 +0,0 @@ -processed 3 tasks - -task 0 'run'. lines 1-6: -Error: Script execution failed with VMError: { - major_status: NUMBER_OF_ARGUMENTS_MISMATCH, - sub_status: None, - location: undefined, - indices: [], - offsets: [], -} - -task 1 'run'. lines 8-13: -Error: Script execution failed with VMError: { - major_status: NUMBER_OF_ARGUMENTS_MISMATCH, - sub_status: None, - location: undefined, - indices: [], - offsets: [], -} diff --git a/third_party/move/move-bytecode-verifier/transactional-tests/tests/script_signature/signer_double_signer.mvir b/third_party/move/move-bytecode-verifier/transactional-tests/tests/script_signature/signer_double_signer.mvir deleted file mode 100644 index 18b599d5fbd30..0000000000000 --- a/third_party/move/move-bytecode-verifier/transactional-tests/tests/script_signature/signer_double_signer.mvir +++ /dev/null @@ -1,20 +0,0 @@ -//# run --signers 0x1 -// missing signer -main(s: signer, s2: signer) { -label b0: - return; -} - -//# run --signers 0x1 --args 0 -// missing signer -main(s: signer, s2: signer, u: u64,) { -label b0: - return; -} - -//# run --args @0x1 0 @0x2 -// no longer an invalid signature, after V5 -main(s: signer, u: u64, s2: signer) { -label b0: - return; -} diff --git a/third_party/move/move-bytecode-verifier/transactional-tests/tests/script_signature/signer_double_signer.v2_exp b/third_party/move/move-bytecode-verifier/transactional-tests/tests/script_signature/signer_double_signer.v2_exp deleted file mode 100644 index 4b0549d55c296..0000000000000 --- a/third_party/move/move-bytecode-verifier/transactional-tests/tests/script_signature/signer_double_signer.v2_exp +++ /dev/null @@ -1,19 +0,0 @@ -processed 3 tasks - -task 0 'run'. lines 1-6: -Error: Script execution failed with VMError: { - major_status: NUMBER_OF_ARGUMENTS_MISMATCH, - sub_status: None, - location: undefined, - indices: [], - offsets: [], -} - -task 1 'run'. lines 8-13: -Error: Script execution failed with VMError: { - major_status: NUMBER_OF_ARGUMENTS_MISMATCH, - sub_status: None, - location: undefined, - indices: [], - offsets: [], -} diff --git a/third_party/move/move-bytecode-verifier/transactional-tests/tests/script_signature/signer_misplaced_signer_arg.exp b/third_party/move/move-bytecode-verifier/transactional-tests/tests/script_signature/signer_misplaced_signer_arg.exp deleted file mode 100644 index 5d92c423f3fd8..0000000000000 --- a/third_party/move/move-bytecode-verifier/transactional-tests/tests/script_signature/signer_misplaced_signer_arg.exp +++ /dev/null @@ -1 +0,0 @@ -processed 2 tasks diff --git a/third_party/move/move-bytecode-verifier/transactional-tests/tests/script_signature/signer_misplaced_signer_arg.mvir b/third_party/move/move-bytecode-verifier/transactional-tests/tests/script_signature/signer_misplaced_signer_arg.mvir deleted file mode 100644 index 7c0bf2513414f..0000000000000 --- a/third_party/move/move-bytecode-verifier/transactional-tests/tests/script_signature/signer_misplaced_signer_arg.mvir +++ /dev/null @@ -1,13 +0,0 @@ -//# run --args 0 @0x1 -// no longer an invalid signature, after V5 -main(u: u64, s: &signer) { -label b0: - return; -} - -//# run --args 0 @0x1 1 -// no longer an invalid signature, after V5 -main(u: u64, s: &signer, u2: u64) { -label b0: - return; -} diff --git a/third_party/move/move-compiler-v2/src/plan_builder.rs b/third_party/move/move-compiler-v2/src/plan_builder.rs index b03c91c712938..7502b6e6c9d2f 100644 --- a/third_party/move/move-compiler-v2/src/plan_builder.rs +++ b/third_party/move/move-compiler-v2/src/plan_builder.rs @@ -162,9 +162,16 @@ fn build_test_info( let mut arguments = Vec::new(); for param in function.get_parameters_ref() { - let Parameter(var, _ty, var_loc) = ¶m; + let Parameter(var, ty, var_loc) = ¶m; match test_annotation_params.get(var) { + Some(MoveValue::Address(addr)) => arguments.push(match ty { + Type::Primitive(PrimitiveType::Signer) => MoveValue::Signer(*addr), + Type::Reference(_, inner) if **inner == Type::Primitive(PrimitiveType::Signer) => { + MoveValue::Signer(*addr) + }, + _ => MoveValue::Address(*addr), + }), Some(value) => arguments.push(value.clone()), None => { let missing_param_msg = "Missing test parameter assignment in test. Expected a \ diff --git a/third_party/move/move-compiler/src/unit_test/plan_builder.rs b/third_party/move/move-compiler/src/unit_test/plan_builder.rs index c53926366cbd9..56b3f5140fd74 100644 --- a/third_party/move/move-compiler/src/unit_test/plan_builder.rs +++ b/third_party/move/move-compiler/src/unit_test/plan_builder.rs @@ -8,6 +8,7 @@ use crate::{ expansion::ast::{ self as E, Address, Attribute, AttributeValue, ModuleAccess_, ModuleIdent, ModuleIdent_, }, + hlir::ast::{BaseType_, SingleType_}, parser::ast::ConstantName, shared::{ known_attributes::{AttributeKind, KnownAttribute, TestingAttribute}, @@ -159,10 +160,19 @@ fn build_test_info<'func>( let test_annotation_params = parse_test_attribute(context, test_attribute, 0); let mut arguments = Vec::new(); - for (var, _) in &function.signature.parameters { + for (var, ty) in &function.signature.parameters { match test_annotation_params.get(&var.value()) { - Some(value) => arguments.push(value.clone()), - None => { + Some(MoveValue::Address(addr)) => match &ty.value { + SingleType_::Base(ty) => arguments.push( + if ty == &BaseType_::address(ty.loc) { + MoveValue::Address(*addr) + } else { + MoveValue::Signer(*addr) + }, + ), + SingleType_::Ref(_, _) => arguments.push(MoveValue::Signer(*addr)), + }, + _ => { let missing_param_msg = "Missing test parameter assignment in test. Expected a \ parameter to be assigned in this attribute"; context.env.add_diag(diag!( diff --git a/third_party/move/move-core/types/src/unit_tests/value_test.rs b/third_party/move/move-core/types/src/unit_tests/value_test.rs index 5c3bb08841503..1519fc7961c57 100644 --- a/third_party/move/move-core/types/src/unit_tests/value_test.rs +++ b/third_party/move/move-core/types/src/unit_tests/value_test.rs @@ -137,3 +137,13 @@ fn nested_typed_struct_deserialization() { }) ); } + +#[test] +fn signer_deserialization() { + let v = MoveValue::Signer(AccountAddress::ZERO); + let bytes = v.simple_serialize().unwrap(); + assert_eq!( + MoveValue::simple_deserialize(&bytes, &crate::value::MoveTypeLayout::Signer).unwrap(), + v + ); +} diff --git a/third_party/move/move-core/types/src/value.rs b/third_party/move/move-core/types/src/value.rs index de4ef817e4832..d3f28133cb374 100644 --- a/third_party/move/move-core/types/src/value.rs +++ b/third_party/move/move-core/types/src/value.rs @@ -465,6 +465,13 @@ impl MoveStructLayout { }, } } + + pub fn signer() -> Self { + MoveStructLayout::RuntimeVariants(vec![vec![MoveTypeLayout::Address], vec![ + MoveTypeLayout::Address, + MoveTypeLayout::Address, + ]]) + } } impl<'d> serde::de::DeserializeSeed<'d> for &MoveTypeLayout { @@ -486,7 +493,13 @@ impl<'d> serde::de::DeserializeSeed<'d> for &MoveTypeLayout { AccountAddress::deserialize(deserializer).map(MoveValue::Address) }, MoveTypeLayout::Signer => { - AccountAddress::deserialize(deserializer).map(MoveValue::Signer) + let (_, fields) = MoveStructLayout::signer() + .deserialize(deserializer)? + .into_optional_variant_and_fields(); + Ok(MoveValue::Signer(match fields[0] { + MoveValue::Address(addr) => addr, + _ => return Err(D::Error::custom("signer deserialization error")), + })) }, MoveTypeLayout::Struct(ty) => Ok(MoveValue::Struct(ty.deserialize(deserializer)?)), MoveTypeLayout::Vector(layout) => Ok(MoveValue::Vector( @@ -691,7 +704,9 @@ impl serde::Serialize for MoveValue { MoveValue::U128(i) => serializer.serialize_u128(*i), MoveValue::U256(i) => i.serialize(serializer), MoveValue::Address(a) => a.serialize(serializer), - MoveValue::Signer(a) => a.serialize(serializer), + MoveValue::Signer(a) => { + MoveStruct::new_variant(0, vec![MoveValue::Address(*a)]).serialize(serializer) + }, MoveValue::Vector(v) => { let mut t = serializer.serialize_seq(Some(v.len()))?; for val in v { diff --git a/third_party/move/move-prover/boogie-backend/src/prelude/prelude.bpl b/third_party/move/move-prover/boogie-backend/src/prelude/prelude.bpl index af262f11c9fbf..970ae252a2a53 100644 --- a/third_party/move/move-prover/boogie-backend/src/prelude/prelude.bpl +++ b/third_party/move/move-prover/boogie-backend/src/prelude/prelude.bpl @@ -1102,13 +1102,25 @@ procedure {:inline 1} $1_Account_create_signer( // Native Signer datatype $signer { - $signer($addr: int) + $signer($addr: int), + $permissioned_signer($addr: int, $permission_addr: int) } + function {:inline} $IsValid'signer'(s: $signer): bool { - $IsValid'address'(s->$addr) + if s is $signer then + $IsValid'address'(s->$addr) + else + $IsValid'address'(s->$addr) && + $IsValid'address'(s->$permission_addr) } + function {:inline} $IsEqual'signer'(s1: $signer, s2: $signer): bool { - s1 == s2 + if s1 is $signer && s2 is $signer then + s1 == s2 + else if s1 is $permissioned_signer && s2 is $permissioned_signer then + s1 == s2 + else + false } procedure {:inline 1} $1_signer_borrow_address(signer: $signer) returns (res: int) { diff --git a/third_party/move/move-prover/tests/sources/functional/loops_with_memory_ops.v2_exp b/third_party/move/move-prover/tests/sources/functional/loops_with_memory_ops.v2_exp index d6f72efdfd3a5..3738bf2876067 100644 --- a/third_party/move/move-prover/tests/sources/functional/loops_with_memory_ops.v2_exp +++ b/third_party/move/move-prover/tests/sources/functional/loops_with_memory_ops.v2_exp @@ -98,8 +98,6 @@ error: unknown assertion failed = y = = at tests/sources/functional/loops_with_memory_ops.move:80: nested_loop2 = at tests/sources/functional/loops_with_memory_ops.move:81: nested_loop2 - = a = - = at tests/sources/functional/loops_with_memory_ops.move:81: nested_loop2 = b = = at tests/sources/functional/loops_with_memory_ops.move:85: nested_loop2 = = diff --git a/third_party/move/move-prover/tests/sources/functional/trace.exp b/third_party/move/move-prover/tests/sources/functional/trace.exp index e24a41719d8a7..5f1a4a7b947ab 100644 --- a/third_party/move/move-prover/tests/sources/functional/trace.exp +++ b/third_party/move/move-prover/tests/sources/functional/trace.exp @@ -47,7 +47,7 @@ error: post-condition does not hold │ = Related Global Memory: = Resource name: TestTracing_R - = Values: {Address(18467): , Default: TestTracing.R{x = 4}} + = Values: {Address(6334): , Default: empty} = Related Bindings: = addr = = exists(addr) = @@ -74,7 +74,7 @@ error: global memory invariant does not hold │ = Related Global Memory: = Resource name: TestTracing_R - = Values: {Address(0): , Default: TestTracing.R{x = 5}} + = Values: {Address(0): , Default: empty} = at tests/sources/functional/trace.move:29: publish_invalid = at tests/sources/functional/trace.move:33: publish_invalid (spec) = `let addr = signer::address_of(s);` = diff --git a/third_party/move/move-prover/tests/sources/functional/trace.v2_exp b/third_party/move/move-prover/tests/sources/functional/trace.v2_exp index 38e6e6733c25b..dff90ea83d206 100644 --- a/third_party/move/move-prover/tests/sources/functional/trace.v2_exp +++ b/third_party/move/move-prover/tests/sources/functional/trace.v2_exp @@ -47,7 +47,7 @@ error: post-condition does not hold │ = Related Global Memory: = Resource name: TestTracing_R - = Values: {Address(18467): , Default: empty} + = Values: {Address(6334): , Default: empty} = Related Bindings: = addr = = exists(addr) = diff --git a/third_party/move/move-stdlib/src/natives/signer.rs b/third_party/move/move-stdlib/src/natives/signer.rs index 3a15343186a0c..97c89e0c24c2e 100644 --- a/third_party/move/move-stdlib/src/natives/signer.rs +++ b/third_party/move/move-stdlib/src/natives/signer.rs @@ -37,10 +37,9 @@ fn native_borrow_address( debug_assert!(arguments.len() == 1); let signer_reference = pop_arg!(arguments, SignerRef); + let out = signer_reference.borrow_signer()?; - Ok(NativeResult::ok(gas_params.base, smallvec![ - signer_reference.borrow_signer()? - ])) + Ok(NativeResult::ok(gas_params.base, smallvec![out])) } pub fn make_native_borrow_address(gas_params: BorrowAddressGasParameters) -> NativeFunction { diff --git a/third_party/move/move-vm/runtime/src/interpreter.rs b/third_party/move/move-vm/runtime/src/interpreter.rs index f45aa01f5fd2b..69169cb6b1177 100644 --- a/third_party/move/move-vm/runtime/src/interpreter.rs +++ b/third_party/move/move-vm/runtime/src/interpreter.rs @@ -2953,7 +2953,7 @@ impl Frame { let resource = interpreter.operand_stack.pop()?; let signer_reference = interpreter.operand_stack.pop_as::()?; let addr = signer_reference - .borrow_field(0)? + .borrow_field(1)? .value_as::()? .read_ref()? .value_as::()?; @@ -2965,7 +2965,7 @@ impl Frame { let resource = interpreter.operand_stack.pop()?; let signer_reference = interpreter.operand_stack.pop_as::()?; let addr = signer_reference - .borrow_field(0)? + .borrow_field(1)? .value_as::()? .read_ref()? .value_as::()?; diff --git a/third_party/move/move-vm/transactional-tests/tests/builtins/gen_move_to.mvir b/third_party/move/move-vm/transactional-tests/tests/builtins/gen_move_to.mvir index a73419b95d424..2f6b7aca551ab 100644 --- a/third_party/move/move-vm/transactional-tests/tests/builtins/gen_move_to.mvir +++ b/third_party/move/move-vm/transactional-tests/tests/builtins/gen_move_to.mvir @@ -155,7 +155,7 @@ module 0x1.M { // // create, publish and exists -//# run --args @0x1 +//# run --signers 0x1 import 0x1.M; main(account: signer) { @@ -169,7 +169,7 @@ label b0: return; } -//# run --args @0x1 +//# run --signers 0x1 import 0x1.M; main(account: signer) { @@ -186,7 +186,7 @@ label b0: return; } -//# run --args @0x1 +//# run --signers 0x1 import 0x1.M; main(account: signer) { @@ -219,7 +219,7 @@ label b0: // // borrows and mutations -//# run --args @0x1 +//# run --signers 0x1 import 0x1.M; main(account: signer) { @@ -243,7 +243,7 @@ label b0: return; } -//# run --args @0x1 +//# run --signers 0x1 import 0x1.M; main(account: signer) { @@ -263,7 +263,7 @@ label b0: // // unpublish, destroy and exists -//# run --args @0x1 +//# run --signers 0x1 import 0x1.M; main(account: signer) { @@ -277,7 +277,7 @@ label b0: return; } -//# run --args @0x1 +//# run --signers 0x1 import 0x1.M; main(account: signer) { @@ -303,7 +303,7 @@ label b0: } -//# run --args @0x1 +//# run --signers 0x1 import 0x1.M; main(account: signer) { diff --git a/third_party/move/move-vm/transactional-tests/tests/entry_points/address_arg_is_not_signer.mvir b/third_party/move/move-vm/transactional-tests/tests/entry_points/address_arg_is_not_signer.mvir index dd04d0efb75cc..a44920339dcfd 100644 --- a/third_party/move/move-vm/transactional-tests/tests/entry_points/address_arg_is_not_signer.mvir +++ b/third_party/move/move-vm/transactional-tests/tests/entry_points/address_arg_is_not_signer.mvir @@ -1,11 +1,11 @@ -//# run --args @0x1 +//# run --signers 0x1 main(s: signer) { label b0: return; } // DEPRECATED signers can now be passed in as addrs -//# run --args @0x0 @0x2 +//# run --signers 0x0 --signers 0x2 main(s: signer, s2: signer) { label b0: return; diff --git a/third_party/move/move-vm/transactional-tests/tests/entry_points/mixed_signer_inputs_function.exp b/third_party/move/move-vm/transactional-tests/tests/entry_points/mixed_signer_inputs_function.exp deleted file mode 100644 index 457ace9c4acb6..0000000000000 --- a/third_party/move/move-vm/transactional-tests/tests/entry_points/mixed_signer_inputs_function.exp +++ /dev/null @@ -1 +0,0 @@ -processed 4 tasks diff --git a/third_party/move/move-vm/transactional-tests/tests/entry_points/mixed_signer_inputs_function.mvir b/third_party/move/move-vm/transactional-tests/tests/entry_points/mixed_signer_inputs_function.mvir deleted file mode 100644 index a55e7a71e4c76..0000000000000 --- a/third_party/move/move-vm/transactional-tests/tests/entry_points/mixed_signer_inputs_function.mvir +++ /dev/null @@ -1,28 +0,0 @@ -//# publish - -// tests various mixed usage of signer in function arguments - -module 0x42.M { - -public main1(s1: signer, s2: &signer, s3: signer) { - label l0: - return; -} - -public main2(s1: &signer, u: u64, s2: signer, f: bool, s3: &signer) { - label l0: - return; -} - -public main3(u: u64, f: bool, a: address, s1: signer, s2: &signer) { - label l0: - return; -} - -} - -//# run 0x42::M::main1 --args @0x1 @0x1 @0x1 - -//# run 0x42::M::main2 --args @0x1 0 @0x1 false @0x1 - -//# run 0x42::M::main3 --args 0 false @0x1 @0x2 @0x3 diff --git a/third_party/move/move-vm/transactional-tests/tests/entry_points/mixed_signer_inputs_function.v2_exp b/third_party/move/move-vm/transactional-tests/tests/entry_points/mixed_signer_inputs_function.v2_exp deleted file mode 100644 index 457ace9c4acb6..0000000000000 --- a/third_party/move/move-vm/transactional-tests/tests/entry_points/mixed_signer_inputs_function.v2_exp +++ /dev/null @@ -1 +0,0 @@ -processed 4 tasks diff --git a/third_party/move/move-vm/transactional-tests/tests/entry_points/mixed_signer_inputs_scripts.exp b/third_party/move/move-vm/transactional-tests/tests/entry_points/mixed_signer_inputs_scripts.exp deleted file mode 100644 index fc5a4436b29d4..0000000000000 --- a/third_party/move/move-vm/transactional-tests/tests/entry_points/mixed_signer_inputs_scripts.exp +++ /dev/null @@ -1 +0,0 @@ -processed 3 tasks diff --git a/third_party/move/move-vm/transactional-tests/tests/entry_points/mixed_signer_inputs_scripts.mvir b/third_party/move/move-vm/transactional-tests/tests/entry_points/mixed_signer_inputs_scripts.mvir deleted file mode 100644 index 7892f86cc7a3a..0000000000000 --- a/third_party/move/move-vm/transactional-tests/tests/entry_points/mixed_signer_inputs_scripts.mvir +++ /dev/null @@ -1,21 +0,0 @@ -//# run --args @0x1 @0x1 @0x1 - -// tests various mixed usage of signer in script arguments - -main(s1: signer, s2: &signer, s3: signer) { - label l0: - return; -} - - -//# run --args @0x1 0 @0x1 false @0x1 -main(s1: &signer, u: u64, s2: signer, f: bool, s3: &signer) { - label l0: - return; -} - -//# run --args 0 false @0x1 @0x2 @0x3 -main(u: u64, f: bool, a: address, s1: signer, s2: &signer) { - label l0: - return; -} diff --git a/third_party/move/move-vm/transactional-tests/tests/entry_points/mixed_signer_inputs_scripts.v2_exp b/third_party/move/move-vm/transactional-tests/tests/entry_points/mixed_signer_inputs_scripts.v2_exp deleted file mode 100644 index fc5a4436b29d4..0000000000000 --- a/third_party/move/move-vm/transactional-tests/tests/entry_points/mixed_signer_inputs_scripts.v2_exp +++ /dev/null @@ -1 +0,0 @@ -processed 3 tasks diff --git a/third_party/move/move-vm/transactional-tests/tests/entry_points/return_values.exp b/third_party/move/move-vm/transactional-tests/tests/entry_points/return_values.exp index 13f10dcbdf982..207d694c94d44 100644 --- a/third_party/move/move-vm/transactional-tests/tests/entry_points/return_values.exp +++ b/third_party/move/move-vm/transactional-tests/tests/entry_points/return_values.exp @@ -2,4 +2,4 @@ processed 2 tasks task 1 'run'. lines 20-20: mutable inputs after call: local#4: { 4 } -return values: 0, { 0000000000000000000000000000000000000000000000000000000000000001 }, { 2 }, { 3 }, 3, 4 +return values: 0, { 0, 0000000000000000000000000000000000000000000000000000000000000001 }, { 2 }, { 3 }, 3, 4 diff --git a/third_party/move/move-vm/transactional-tests/tests/entry_points/return_values.mvir b/third_party/move/move-vm/transactional-tests/tests/entry_points/return_values.mvir index 875876e59f9df..1210f152defe0 100644 --- a/third_party/move/move-vm/transactional-tests/tests/entry_points/return_values.mvir +++ b/third_party/move/move-vm/transactional-tests/tests/entry_points/return_values.mvir @@ -6,8 +6,8 @@ module 0x42.M { struct S { f: u64 } public t( - x: u64, a: signer, + x: u64, s: Self.S, r1: &Self.S, r2: &mut Self.S @@ -17,4 +17,4 @@ module 0x42.M { } } -//# run 0x42::M::t --args 0 @0x1 2 3 4 +//# run 0x42::M::t --signers 0x1 --args 0 2 3 4 diff --git a/third_party/move/move-vm/transactional-tests/tests/entry_points/script_type_args_type_eq.mvir b/third_party/move/move-vm/transactional-tests/tests/entry_points/script_type_args_type_eq.mvir index 303be015fcb26..07f1320cb41ea 100644 --- a/third_party/move/move-vm/transactional-tests/tests/entry_points/script_type_args_type_eq.mvir +++ b/third_party/move/move-vm/transactional-tests/tests/entry_points/script_type_args_type_eq.mvir @@ -20,7 +20,7 @@ module 0x42.M { } // check: "Keep(EXECUTED)" -//# run --type-args u64 --args @0x1 +//# run --type-args u64 --signers 0x1 import 0x42.M; main(account: signer) { @@ -32,7 +32,7 @@ label b0: -//# run --type-args 0x42::M::Item --args @0x2 +//# run --type-args 0x42::M::Item --signers 0x2 import 0x42.M; main(account: signer) { @@ -43,7 +43,7 @@ label b0: } -//# run --type-args 0x42::M::Cup<0x42::M::Cup>> --args @0x3 +//# run --type-args 0x42::M::Cup<0x42::M::Cup>> --signers 0x3 import 0x42.M; main(account: signer) { diff --git a/third_party/move/move-vm/transactional-tests/tests/entry_points/serializer_deserializer.move b/third_party/move/move-vm/transactional-tests/tests/entry_points/serializer_deserializer.move index 85e996fad40ac..500f0c1f83633 100644 --- a/third_party/move/move-vm/transactional-tests/tests/entry_points/serializer_deserializer.move +++ b/third_party/move/move-vm/transactional-tests/tests/entry_points/serializer_deserializer.move @@ -37,7 +37,7 @@ module 0x42::t { } -//# run 0x42::t::add --args @0x42 +//# run 0x42::t::add --signers 0x42 //# view --address 0x42 --resource 0x42::t::Ints diff --git a/third_party/move/move-vm/transactional-tests/tests/recursion/runtime_layout_deeply_nested.mvir b/third_party/move/move-vm/transactional-tests/tests/recursion/runtime_layout_deeply_nested.mvir index 9044139ecd6f3..5a3ffa6b060f3 100644 --- a/third_party/move/move-vm/transactional-tests/tests/recursion/runtime_layout_deeply_nested.mvir +++ b/third_party/move/move-vm/transactional-tests/tests/recursion/runtime_layout_deeply_nested.mvir @@ -66,7 +66,7 @@ module 0x42.M { } -//# run --args @0x1 +//# run --signers 0x1 import 0x42.M; main(account: signer) { @@ -76,7 +76,7 @@ label b0: return; } -//# run --args @0x2 +//# run --signers 0x2 import 0x42.M; main(account: signer) { @@ -86,7 +86,7 @@ label b0: } -//# run --args @0x3 +//# run --signers 0x3 import 0x42.M; main(account: signer) { diff --git a/third_party/move/move-vm/types/src/value_serde.rs b/third_party/move/move-vm/types/src/value_serde.rs index 5f17bfe9b3848..c7f2c74b0e4d9 100644 --- a/third_party/move/move-vm/types/src/value_serde.rs +++ b/third_party/move/move-vm/types/src/value_serde.rs @@ -104,6 +104,7 @@ impl CustomSerializer for RelaxedCustomSerDe { custom_serializer: None::<&RelaxedCustomSerDe>, layout, value: &value.0, + legacy_signer: false, } .serialize(serializer) } @@ -134,6 +135,7 @@ pub fn serialize_and_allow_delayed_values( custom_serializer: Some(&native_serializer), layout, value: &value.0, + legacy_signer: false, }; bcs::to_bytes(&value) .ok() @@ -163,6 +165,7 @@ pub fn serialized_size_allowing_delayed_values( custom_serializer: Some(&native_serializer), layout, value: &value.0, + legacy_signer: true, }; bcs::serialized_size(&value).map_err(|e| { PartialVMError::new(StatusCode::VALUE_SERIALIZATION_ERROR).with_message(format!( @@ -232,6 +235,7 @@ impl<'a, I: From + ExtractWidth + ExtractUniqueIndex> CustomSerializer custom_serializer: None::<&RelaxedCustomSerDe>, layout, value: &value.0, + legacy_signer: false, } .serialize(serializer) } @@ -291,6 +295,7 @@ pub fn serialize_and_replace_ids_with_values + ExtractWidth + Extra custom_serializer: Some(&custom_serializer), layout, value: &value.0, + legacy_signer: false, }; bcs::to_bytes(&value).ok().filter(|_| { // Should never happen, it should always fail first in serialize_and_allow_delayed_values diff --git a/third_party/move/move-vm/types/src/values/serialization_tests.rs b/third_party/move/move-vm/types/src/values/serialization_tests.rs index 6085a50183e2c..a3ecf6b50c324 100644 --- a/third_party/move/move-vm/types/src/values/serialization_tests.rs +++ b/third_party/move/move-vm/types/src/values/serialization_tests.rs @@ -244,3 +244,26 @@ fn test_serialized_size() { assert_err!(serialized_size_allowing_delayed_values(&value, &layout)); } } + +#[test] +fn signer_round_trip_vm_value() { + let v = MoveValue::Signer(AccountAddress::ZERO); + let bytes = v.simple_serialize().unwrap(); + let vm_value = Value::simple_deserialize(&bytes, &MoveTypeLayout::Signer).unwrap(); + let vm_bytes = serialize_and_allow_delayed_values(&vm_value, &MoveTypeLayout::Signer) + .unwrap() + .unwrap(); + assert_eq!( + v, + MoveValue::simple_deserialize(&vm_bytes, &MoveTypeLayout::Signer).unwrap() + ); + + let permissioned_signer = Value::permissioned_signer(AccountAddress::ZERO, AccountAddress::ONE); + let bytes = permissioned_signer + .simple_serialize(&MoveTypeLayout::Signer) + .unwrap(); + assert_eq!( + v, + MoveValue::simple_deserialize(&bytes, &MoveTypeLayout::Signer).unwrap(), + ); +} diff --git a/third_party/move/move-vm/types/src/values/values_impl.rs b/third_party/move/move-vm/types/src/values/values_impl.rs index 42fbe5d9278c3..e0edf03a8d9f6 100644 --- a/third_party/move/move-vm/types/src/values/values_impl.rs +++ b/third_party/move/move-vm/types/src/values/values_impl.rs @@ -284,7 +284,10 @@ impl Container { } fn signer(x: AccountAddress) -> Self { - Container::Struct(Rc::new(RefCell::new(vec![ValueImpl::Address(x)]))) + Container::Struct(Rc::new(RefCell::new(vec![ + ValueImpl::U16(0), + ValueImpl::Address(x), + ]))) } } @@ -1506,7 +1509,31 @@ impl Locals { impl SignerRef { pub fn borrow_signer(&self) -> PartialVMResult { - Ok(Value(self.0.borrow_elem(0)?)) + Ok(Value(self.0.borrow_elem(1)?)) + } + + pub fn is_permissioned(&self) -> PartialVMResult { + match &self.0 { + ContainerRef::Local(Container::Struct(s)) => { + Ok(*s.borrow()[0].as_value_ref::()? == 1) + }, + _ => Err( + PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR) + .with_message(format!("unexpected signer value: {:?}", self)), + ), + } + } + + pub fn permissioned_signer(&self) -> PartialVMResult { + match &self.0 { + ContainerRef::Local(Container::Struct(s)) => Ok(Value::address( + *s.borrow()[2].as_value_ref::()?, + )), + _ => Err( + PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR) + .with_message(format!("unexpected signer value: {:?}", self)), + ), + } } } @@ -1669,6 +1696,13 @@ impl Value { Self(ValueImpl::Container(Container::signer(x))) } + pub fn permissioned_signer(x: AccountAddress, perm_storage_address: AccountAddress) -> Self { + Self::struct_(Struct::pack_variant(1, vec![ + Value::address(x), + Value::address(perm_storage_address), + ])) + } + /// Create a "unowned" reference to a signer value (&signer) for populating the &signer in /// execute function pub fn signer_reference(x: AccountAddress) -> Self { @@ -3647,6 +3681,7 @@ impl Value { custom_serializer: None::<&RelaxedCustomSerDe>, layout, value: &self.0, + legacy_signer: false, }) .ok() } @@ -3666,6 +3701,7 @@ impl Struct { custom_serializer: None::<&RelaxedCustomSerDe>, layout, value: &self.fields, + legacy_signer: false, }) .ok() } @@ -3680,6 +3716,7 @@ pub(crate) struct SerializationReadyValue<'c, 'l, 'v, L, V, C> { pub(crate) layout: &'l L, // Value to serialize. pub(crate) value: &'v V, + pub(crate) legacy_signer: bool, } fn invariant_violation(message: String) -> S::Error { @@ -3711,6 +3748,7 @@ impl<'c, 'l, 'v, C: CustomSerializer> serde::Serialize custom_serializer: self.custom_serializer, layout: struct_layout, value: &*r.borrow(), + legacy_signer: self.legacy_signer, }) .serialize(serializer) }, @@ -3735,6 +3773,7 @@ impl<'c, 'l, 'v, C: CustomSerializer> serde::Serialize custom_serializer: self.custom_serializer, layout, value, + legacy_signer: self.legacy_signer, })?; } t.end() @@ -3748,19 +3787,25 @@ impl<'c, 'l, 'v, C: CustomSerializer> serde::Serialize // Signer. (L::Signer, ValueImpl::Container(Container::Struct(r))) => { - let v = r.borrow(); - if v.len() != 1 { - return Err(invariant_violation::(format!( - "cannot serialize container as a signer -- expected 1 field got {}", - v.len() - ))); + if self.legacy_signer { + r.borrow()[1] + .as_value_ref::() + .map_err(|_| { + invariant_violation::(format!( + "cannot serialize container {:?} as {:?}", + self.value, self.layout + )) + })? + .serialize(serializer) + } else { + (SerializationReadyValue { + custom_serializer: self.custom_serializer, + layout: &MoveStructLayout::signer(), + value: &*r.borrow(), + legacy_signer: self.legacy_signer, + }) + .serialize(serializer) } - (SerializationReadyValue { - custom_serializer: self.custom_serializer, - layout: &L::Address, - value: &v[0], - }) - .serialize(serializer) }, // Delayed values. For their serialization, we must have custom @@ -3821,6 +3866,7 @@ impl<'c, 'l, 'v, C: CustomSerializer> serde::Serialize custom_serializer: self.custom_serializer, layout: &variant_layouts[0], value: &values[0], + legacy_signer: self.legacy_signer, }, ), _ => { @@ -3835,6 +3881,7 @@ impl<'c, 'l, 'v, C: CustomSerializer> serde::Serialize custom_serializer: self.custom_serializer, layout, value, + legacy_signer: self.legacy_signer, })? } t.end() @@ -3854,6 +3901,7 @@ impl<'c, 'l, 'v, C: CustomSerializer> serde::Serialize custom_serializer: self.custom_serializer, layout: field_layout, value, + legacy_signer: self.legacy_signer, })?; } t.end() @@ -3892,7 +3940,13 @@ impl<'d, 'c, C: CustomDeserializer> serde::de::DeserializeSeed<'d> L::U128 => u128::deserialize(deserializer).map(Value::u128), L::U256 => u256::U256::deserialize(deserializer).map(Value::u256), L::Address => AccountAddress::deserialize(deserializer).map(Value::address), - L::Signer => AccountAddress::deserialize(deserializer).map(Value::signer), + L::Signer => { + let seed = DeserializationSeed { + custom_deserializer: self.custom_deserializer, + layout: &MoveStructLayout::signer(), + }; + Ok(Value::struct_(seed.deserialize(deserializer)?)) + }, // Structs. L::Struct(struct_layout) => { @@ -4658,10 +4712,7 @@ impl ValueImpl { (L::Signer, ValueImpl::Container(Container::Struct(r))) => { let v = r.borrow(); - if v.len() != 1 { - panic!("Unexpected signer layout: {:?}", v); - } - match &v[0] { + match &v[1] { ValueImpl::Address(a) => MoveValue::Signer(*a), v => panic!("Unexpected non-address while converting signer: {:?}", v), } diff --git a/third_party/move/scripts/move_pr.sh b/third_party/move/scripts/move_pr.sh index 56b1ef095cec7..ca79da100b496 100755 --- a/third_party/move/scripts/move_pr.sh +++ b/third_party/move/scripts/move_pr.sh @@ -186,9 +186,9 @@ if [ ! -z "$INTEGRATION_TEST" ]; then echo "*************** [move-pr] Running integration tests" ( cd $BASE - MOVE_COMPILER_V2=false cargo build $CARGO_OP_PARAMS \ + MOVE_COMPILER_V2=false MOVE_LANGUAGE_V2=true cargo build $CARGO_OP_PARAMS \ $MOVE_CRATES $MOVE_CRATES_V2_ENV_DEPENDENT - MOVE_COMPILER_V2=false cargo nextest run $CARGO_NEXTEST_PARAMS \ + MOVE_COMPILER_V2=false MOVE_LANGUAGE_V2=true cargo nextest run $CARGO_NEXTEST_PARAMS \ $MOVE_CRATES $MOVE_CRATES_V2_ENV_DEPENDENT ) fi