From c11d774b4e877da6108f3d29dc85dc316b45e7ca 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 --- Cargo.lock | 118 ++++++------ aptos-move/e2e-move-tests/src/tests/gas.rs | 10 +- aptos-move/e2e-tests/src/executor.rs | 17 +- .../doc/transaction_context.md | 2 + .../sources/permissioned_signer.spec.move | 177 ++++++++++++++++++ .../sources/transaction_context.spec.move | 2 + .../framework/aptos-stdlib/doc/smart_table.md | 2 + .../data_structures/smart_table.spec.move | 2 + aptos-move/framework/src/aptos.rs | 2 +- aptos-move/framework/src/natives/mod.rs | 5 + .../src/natives/permissioned_signer.rs | 106 +++++++++++ .../framework/src/natives/string_utils.rs | 2 +- .../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 | 6 +- .../move/move-vm/runtime/src/interpreter.rs | 4 +- .../move/move-vm/types/src/value_serde.rs | 5 + .../types/src/values/serialization_tests.rs | 14 ++ .../move-vm/types/src/values/values_impl.rs | 82 ++++++-- third_party/move/scripts/move_pr.sh | 2 +- 26 files changed, 532 insertions(+), 106 deletions(-) create mode 100644 aptos-move/framework/aptos-framework/sources/permissioned_signer.spec.move create mode 100644 aptos-move/framework/src/natives/permissioned_signer.rs diff --git a/Cargo.lock b/Cargo.lock index fa0e56a9e3823c..89f40f63d6a348 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -149,7 +149,7 @@ checksum = "fe233a377643e0fc1a56421d7c90acdec45c291b30345eb9f08e8d0ddce5a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -5145,7 +5145,7 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -5212,7 +5212,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -5229,7 +5229,7 @@ checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -5574,7 +5574,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -6290,7 +6290,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -6987,7 +6987,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -7049,7 +7049,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -7071,7 +7071,7 @@ checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core 0.20.9", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -7162,7 +7162,7 @@ checksum = "4e018fccbeeb50ff26562ece792ed06659b9c2dae79ece77c4456bb10d9bf79b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -7222,7 +7222,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -7243,7 +7243,7 @@ dependencies = [ "darling 0.20.9", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -7253,7 +7253,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" dependencies = [ "derive_builder_core", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -7336,7 +7336,7 @@ dependencies = [ "diesel_table_macro_syntax", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -7356,7 +7356,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc5557efc453706fed5e4fa85006fe9817c224c3f480a34c7e5959fd700921c5" dependencies = [ - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -7725,7 +7725,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -8305,7 +8305,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -8437,7 +8437,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -9074,9 +9074,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" [[package]] name = "hdrhistogram" @@ -9776,7 +9776,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.15.0", + "hashbrown 0.15.1", "serde", ] @@ -10882,7 +10882,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -11975,9 +11975,9 @@ checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" [[package]] name = "newtype-uuid" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4933943834e236c864a48aefdc2da43885dbd5eb77bff3ab20f31e0c3146f5" +checksum = "4c8781e2ef64806278a55ad223f0bc875772fd40e1fe6e73e8adbf027817229d" dependencies = [ "uuid", ] @@ -12365,7 +12365,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -12618,7 +12618,7 @@ dependencies = [ "parquet", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -12828,7 +12828,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -12946,7 +12946,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -13119,7 +13119,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -13160,7 +13160,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.48", + "syn 2.0.87", "thiserror", ] @@ -13522,9 +13522,9 @@ checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" [[package]] name = "proc-macro2" -version = "1.0.76" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] @@ -13646,7 +13646,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -13758,7 +13758,7 @@ dependencies = [ "itertools 0.11.0", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -13771,7 +13771,7 @@ dependencies = [ "itertools 0.13.0", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -14258,7 +14258,7 @@ checksum = "5fddb4f8d99b0a2ebafc65a87a69a7b9875e4b1ae1f00db265d300ef7f28bccc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -15204,7 +15204,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -15215,7 +15215,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -15269,7 +15269,7 @@ checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -15319,7 +15319,7 @@ dependencies = [ "darling 0.20.9", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -16031,7 +16031,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -16044,7 +16044,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -16101,9 +16101,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", @@ -16301,7 +16301,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -16312,7 +16312,7 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", "test-case-core", ] @@ -16389,22 +16389,22 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.65" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.65" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -16569,7 +16569,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -17005,7 +17005,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -17142,7 +17142,7 @@ checksum = "b9c81686f7ab4065ccac3df7a910c4249f8c0f3fb70421d6ddec19b9311f63f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -17182,7 +17182,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -17722,7 +17722,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", "wasm-bindgen-shared", ] @@ -17756,7 +17756,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -18279,7 +18279,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] @@ -18299,7 +18299,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.87", ] [[package]] diff --git a/aptos-move/e2e-move-tests/src/tests/gas.rs b/aptos-move/e2e-move-tests/src/tests/gas.rs index 240d2a30ecc353..bb629e184d2f23 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-tests/src/executor.rs b/aptos-move/e2e-tests/src/executor.rs index 4c44a7e585c634..008d88010c51ab 100644 --- a/aptos-move/e2e-tests/src/executor.rs +++ b/aptos-move/e2e-tests/src/executor.rs @@ -67,6 +67,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}, @@ -998,13 +999,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 cc7d9010ffc74d..d4dbf2d6358111 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 00000000000000..f5818a2e9a0c95 --- /dev/null +++ b/aptos-move/framework/aptos-framework/sources/permissioned_signer.spec.move @@ -0,0 +1,177 @@ +spec aptos_framework::permissioned_signer { + + spec module { + 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_signer(s: signer): signer; + + spec permission_signer(permissioned: &signer): signer { + pragma opaque; + aborts_if [abstract] !spec_is_permissioned_signer(permissioned); + ensures [abstract] result == spec_permission_signer(permissioned); + } + + spec fun spec_signer_from_permissioned_impl(master_addr: address, permission_addr: address): signer; + + spec signer_from_permissioned_impl(master_addr: address, permission_addr: address): signer { + pragma opaque; + ensures [abstract] result == spec_signer_from_permissioned_impl(master_addr, permission_addr); + } + + spec create_permissioned_handle(master: &signer): PermissionedHandle { + use aptos_framework::transaction_context; + pragma opaque; + aborts_if [abstract] spec_is_permissioned_signer(master); + let permission_addr = transaction_context::spec_generate_unique_address(); + modifies global(permission_addr); + let master_addr = signer::address_of(master); + ensures result.master_addr == master_addr; + ensures result.permission_addr == permission_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 permission_addr = transaction_context::spec_generate_unique_address(); + modifies global(permission_addr); + let master_addr = signer::address_of(master); + modifies global(master_addr); + ensures result.master_addr == master_addr; + ensures result.permission_addr == permission_addr; + ensures result.expiration_time == expiration_time; + ensures vector::spec_contains(global(master_addr).active_handles, permission_addr); + ensures exists(master_addr); + } + + spec destroy_permissioned_handle(p: PermissionedHandle) { + ensures !exists(p.permission_addr); + } + + spec destroy_storable_permissioned_handle(p: StorablePermissionedHandle) { + ensures !exists(p.permission_addr); + let post granted_permissions = global(p.master_addr); + // ensures [abstract] !vector::spec_contains(granted_permissions.active_handles, p.permission_addr); + } + + spec revoke_permission_handle(s: &signer, permission_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(signer::address_of(spec_permission_signer(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 = signer::address_of(spec_permission_signer(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 = signer::address_of(spec_permission_signer(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 = signer::address_of(spec_permission_signer(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 { + aborts_if !spec_is_permissioned_signer(s); + let permissioned_signer_addr = signer::address_of(spec_permission_signer(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 f9837e26e6a757..07487cb0919aed 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 ac5388661f2caf..83eb27ba47fff6 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 d905a0a40bb3ac..4344eb2329efbd 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/src/aptos.rs b/aptos-move/framework/src/aptos.rs index 6717a00135be4e..9e030e69b30bf1 100644 --- a/aptos-move/framework/src/aptos.rs +++ b/aptos-move/framework/src/aptos.rs @@ -113,7 +113,7 @@ impl ReleaseTarget { output_format: None, }), skip_fetch_latest_git_deps: true, - ..BuildOptions::default() + ..BuildOptions::move_2() }, packages: packages.iter().map(|(path, _)| path.to_owned()).collect(), rust_bindings: packages diff --git a/aptos-move/framework/src/natives/mod.rs b/aptos-move/framework/src/natives/mod.rs index dcfc80407f9329..956c590b4afc8d 100644 --- a/aptos-move/framework/src/natives/mod.rs +++ b/aptos-move/framework/src/natives/mod.rs @@ -15,6 +15,7 @@ pub mod function_info; pub mod hash; pub mod object; pub mod object_code_deployment; +pub mod permissioned_signer; pub mod randomness; pub mod state_storage; pub mod string_utils; @@ -91,6 +92,10 @@ pub fn all_natives( "dispatchable_fungible_asset", dispatchable_fungible_asset::make_all(builder) ); + add_natives_from_module!( + "permissioned_signer", + permissioned_signer::make_all(builder) + ); if inject_create_signer_for_gov_sim { add_natives_from_module!( diff --git a/aptos-move/framework/src/natives/permissioned_signer.rs b/aptos-move/framework/src/natives/permissioned_signer.rs new file mode 100644 index 00000000000000..3d34e89a4ec38c --- /dev/null +++ b/aptos-move/framework/src/natives/permissioned_signer.rs @@ -0,0 +1,106 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 +use aptos_native_interface::{ + safely_pop_arg, RawSafeNative, SafeNativeBuilder, SafeNativeContext, SafeNativeError, + SafeNativeResult, +}; +use move_core_types::account_address::AccountAddress; +use move_vm_runtime::native_functions::NativeFunction; +use move_vm_types::{ + loaded_data::runtime_types::Type, + values::{SignerRef, Struct, Value}, +}; +use smallvec::{smallvec, SmallVec}; +use std::collections::VecDeque; + +/*************************************************************************************************** + * native fun is_permissioned_signer + * + * Returns true if the signer passed in is a permissioned signer + * gas cost: base_cost + * + **************************************************************************************************/ +fn native_is_permissioned_signer( + _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()?; + let result = s_arg.is_permissioned()?; + + Ok(smallvec![Value::bool(result)]) +} + +/*************************************************************************************************** + * native fun permission_signer + * + * Returns the permission signer if the signer passed in is a permissioned signer + * gas cost: base_cost + * + **************************************************************************************************/ +fn native_permission_signer( + _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()?; + if !s_arg.is_permissioned()? { + return Err(SafeNativeError::Abort { abort_code: 3 }); + } + + Ok(smallvec![s_arg.permissioned_signer()?]) +} + +/*************************************************************************************************** + * native fun signer_from_permissioned + * + * 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()?; + + Ok(smallvec![Value::struct_(Struct::pack_variant(1, vec![ + Value::address(master_addr), + Value::address(permission_addr) + ]))]) +} + +/*************************************************************************************************** + * module + * + **************************************************************************************************/ +pub fn make_all( + builder: &SafeNativeBuilder, +) -> impl Iterator + '_ { + let natives = [ + ( + "is_permissioned_signer", + native_is_permissioned_signer as RawSafeNative, + ), + ("permission_signer", native_permission_signer), + ( + "signer_from_permissioned_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 0a4c7c71583f89..3cb87c669b2394 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/third_party/move/move-compiler-v2/src/plan_builder.rs b/third_party/move/move-compiler-v2/src/plan_builder.rs index 804ba329bd0a43..4906ca1cba5f37 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 c53926366cbd92..56b3f5140fd746 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 5c3bb088415035..1519fc7961c57a 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 49a4d4eada8df7..7fb43bcae11ed1 100644 --- a/third_party/move/move-core/types/src/value.rs +++ b/third_party/move/move-core/types/src/value.rs @@ -452,6 +452,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 { @@ -473,7 +480,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( @@ -678,7 +691,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 af262f11c9fbf2..970ae252a2a530 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 d6f72efdfd3a5c..3738bf28760678 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 e24a41719d8a78..5f1a4a7b947ab0 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 38e6e6733c25b2..dff90ea83d206e 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 3a15343186a0ca..5d4c0089f9b236 100644 --- a/third_party/move/move-stdlib/src/natives/signer.rs +++ b/third_party/move/move-stdlib/src/natives/signer.rs @@ -37,10 +37,10 @@ fn native_borrow_address( debug_assert!(arguments.len() == 1); let signer_reference = pop_arg!(arguments, SignerRef); + let out = signer_reference.borrow_signer()?; + println!("borrow_address: {:?}", out); - 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 f45aa01f5fd2b3..69169cb6b1177d 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/types/src/value_serde.rs b/third_party/move/move-vm/types/src/value_serde.rs index 5f17bfe9b38489..c7f2c74b0e4d99 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 6085a50183e2cb..7b4aef0f147080 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,17 @@ 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() + ) +} 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 006c16d6b9dd1b..1001f35288b80c 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 @@ -283,7 +283,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), + ]))) } } @@ -1058,7 +1061,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::signer( + *s.borrow()[2].as_value_ref::()?, + )), + _ => Err( + PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR) + .with_message(format!("unexpected signer value: {:?}", self)), + ), + } } } @@ -3123,6 +3150,7 @@ impl Value { custom_serializer: None::<&RelaxedCustomSerDe>, layout, value: &self.0, + legacy_signer: false, }) .ok() } @@ -3142,6 +3170,7 @@ impl Struct { custom_serializer: None::<&RelaxedCustomSerDe>, layout, value: &self.fields, + legacy_signer: false, }) .ok() } @@ -3156,6 +3185,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 { @@ -3187,6 +3217,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) }, @@ -3211,6 +3242,7 @@ impl<'c, 'l, 'v, C: CustomSerializer> serde::Serialize custom_serializer: self.custom_serializer, layout, value, + legacy_signer: self.legacy_signer, })?; } t.end() @@ -3224,19 +3256,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 @@ -3297,6 +3335,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, }, ), _ => { @@ -3311,6 +3350,7 @@ impl<'c, 'l, 'v, C: CustomSerializer> serde::Serialize custom_serializer: self.custom_serializer, layout, value, + legacy_signer: self.legacy_signer, })? } t.end() @@ -3330,6 +3370,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() @@ -3368,7 +3409,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) => { @@ -4134,10 +4181,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 48f8af6239bf6d..3204e8e6e3bf97 100755 --- a/third_party/move/scripts/move_pr.sh +++ b/third_party/move/scripts/move_pr.sh @@ -199,7 +199,7 @@ if [ ! -z "$COMPILER_V2_TEST" ]; then MVC_DOCGEN_OUTPUT_DIR=tests/compiler-v2-doc MOVE_COMPILER_V2=true cargo build $CARGO_OP_PARAMS \ $MOVE_CRATES_V2_ENV_DEPENDENT MVC_DOCGEN_OUTPUT_DIR=tests/compiler-v2-doc \ - MOVE_COMPILER_V2=true cargo nextest run $CARGO_NEXTEST_PARAMS \ + MOVE_COMPILER_V2=true MOVE_LANGUAGE_V2=true cargo nextest run $CARGO_NEXTEST_PARAMS \ $MOVE_CRATES_V2_ENV_DEPENDENT ) fi