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..b9bb7deccfe55 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 @@ -6,7 +6,7 @@ use crate::{ gas_feature_versions::{RELEASE_V1_14, RELEASE_V1_8, RELEASE_V1_9_SKIPPED}, gas_schedule::NativeGasParameters, - ver::gas_feature_versions::{RELEASE_V1_12, RELEASE_V1_13, RELEASE_V1_23}, + ver::gas_feature_versions::{RELEASE_V1_12, RELEASE_V1_13, RELEASE_V1_23, RELEASE_V1_26}, }; use aptos_gas_algebra::{ InternalGas, InternalGasPerAbstractValueUnit, InternalGasPerArg, InternalGasPerByte, @@ -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, { RELEASE_V1_26 => "permissioned_signer.permission_address.base"}, 1102], + [is_permissioned_signer_base: InternalGas, { RELEASE_V1_26 => "permissioned_signer.is_permissioned_signer.base"}, 1102], + [signer_from_permissioned_handle_base: InternalGas, { RELEASE_V1_26 => "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/aptos-gas-schedule/src/ver.rs b/aptos-move/aptos-gas-schedule/src/ver.rs index 9e40e1d833880..feb190e3b8e0e 100644 --- a/aptos-move/aptos-gas-schedule/src/ver.rs +++ b/aptos-move/aptos-gas-schedule/src/ver.rs @@ -89,4 +89,5 @@ pub mod gas_feature_versions { pub const RELEASE_V1_22: u64 = 26; pub const RELEASE_V1_23: u64 = 27; pub const RELEASE_V1_24: u64 = 28; + pub const RELEASE_V1_26: u64 = 29; } diff --git a/aptos-move/aptos-vm-profiling/src/bins/run_move.rs b/aptos-move/aptos-vm-profiling/src/bins/run_move.rs index 667a7c49c0bb4..3a1c51b715662 100644 --- a/aptos-move/aptos-vm-profiling/src/bins/run_move.rs +++ b/aptos-move/aptos-vm-profiling/src/bins/run_move.rs @@ -37,7 +37,7 @@ fn make_native_create_signer() -> NativeFunction { let address = pop_arg!(args, AccountAddress); - Ok(NativeResult::ok(0.into(), smallvec![Value::signer( + Ok(NativeResult::ok(0.into(), smallvec![Value::master_signer( address )])) }) diff --git a/aptos-move/e2e-move-tests/src/tests/gas.rs b/aptos-move/e2e-move-tests/src/tests/gas.rs index ceab7b3508fa9..5af30e8956693 100644 --- a/aptos-move/e2e-move-tests/src/tests/gas.rs +++ b/aptos-move/e2e-move-tests/src/tests/gas.rs @@ -28,7 +28,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; @@ -55,7 +55,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(), ], @@ -64,7 +66,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/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 2d3b78221b400..c2039a589d6d6 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}, @@ -1042,13 +1043,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/doc/util.md b/aptos-move/framework/aptos-framework/doc/util.md
index 58f3e29748c93..ca6b1f1264c0e 100644
--- a/aptos-move/framework/aptos-framework/doc/util.md
+++ b/aptos-move/framework/aptos-framework/doc/util.md
@@ -29,6 +29,8 @@ Note that this function does not put any constraint on T
. If code u
deserialized a linear value, its their responsibility that the data they deserialize is
owned.
+Function would abort if T has signer in it.
+
public(friend) fun from_bytes<T>(bytes: vector<u8>): T
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-framework/sources/util.move b/aptos-move/framework/aptos-framework/sources/util.move
index 332afa299c784..f57d3cfbf26cb 100644
--- a/aptos-move/framework/aptos-framework/sources/util.move
+++ b/aptos-move/framework/aptos-framework/sources/util.move
@@ -8,9 +8,17 @@ module aptos_framework::util {
/// Note that this function does not put any constraint on `T`. If code uses this function to
/// deserialized a linear value, its their responsibility that the data they deserialize is
/// owned.
+ ///
+ /// Function would abort if T has signer in it.
public(friend) native fun from_bytesT
. If code u
deserialize a linear value, its their responsibility that the data they deserialize is
owned.
+Function would abort if T has signer in it.
+
public(friend) fun from_bytes<T>(bytes: vector<u8>): T
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 destroyv
in BCS (Binary Canonical Serialization) format.
Aborts with 0x1c5
error code if serialization fails.
diff --git a/aptos-move/framework/move-stdlib/doc/signer.md b/aptos-move/framework/move-stdlib/doc/signer.md
index f6de8799b571c..13e9e008ef8d3 100644
--- a/aptos-move/framework/move-stdlib/doc/signer.md
+++ b/aptos-move/framework/move-stdlib/doc/signer.md
@@ -18,12 +18,26 @@
## Function `borrow_address`
-Borrows the address of the signer
-Conceptually, you can think of the signer
as being a struct wrapper around an
-address
+signer is a builtin move type that represents an address that has been verfied by the VM.
+
+VM Runtime representation is equivalent to following:
+```
+enum signer has drop {
+Master { account: address },
+Permissioned { account: address, permissions_address: address },
+}
+```
+
+for bcs serialization:
+
```
-struct signer has drop { addr: address }
+struct signer has drop {
+account: address,
+}
```
+^ The discrepency is needed to maintain backwards compatibility of signer serialization
+semantics.
+
borrow_address
borrows this inner field
diff --git a/aptos-move/framework/move-stdlib/sources/bcs.move b/aptos-move/framework/move-stdlib/sources/bcs.move
index b803428eef991..1113a02c9c269 100644
--- a/aptos-move/framework/move-stdlib/sources/bcs.move
+++ b/aptos-move/framework/move-stdlib/sources/bcs.move
@@ -5,6 +5,8 @@
module std::bcs {
use std::option::Option;
+ /// Note: all natives would fail if the MoveValue contains a permissioned signer in it.
+
/// Returns the binary representation of `v` in BCS (Binary Canonical Serialization) format.
/// Aborts with `0x1c5` error code if serialization fails.
native public fun to_bytesborrow_address
borrows this inner field
public fun borrow_address(s: &signer): &address
diff --git a/third_party/move/move-stdlib/sources/signer.move b/third_party/move/move-stdlib/sources/signer.move
index 1996b4331e987..16d5c2cc8ddae 100644
--- a/third_party/move/move-stdlib/sources/signer.move
+++ b/third_party/move/move-stdlib/sources/signer.move
@@ -1,11 +1,25 @@
module std::signer {
- // Borrows the address of the signer
- // Conceptually, you can think of the `signer` as being a struct wrapper arround an
- // address
- // ```
- // struct signer has drop { addr: address }
- // ```
- // `borrow_address` borrows this inner field
+ /// signer is a builtin move type that represents an address that has been verfied by the VM.
+ ///
+ /// VM Runtime representation is equivalent to following:
+ /// ```
+ /// enum signer has drop {
+ /// Master { account: address },
+ /// Permissioned { account: address, permissions_address: address },
+ /// }
+ /// ```
+ ///
+ /// for bcs serialization:
+ ///
+ /// ```
+ /// struct signer has drop {
+ /// account: address,
+ /// }
+ /// ```
+ /// ^ The discrepency is needed to maintain backwards compatibility of signer serialization
+ /// semantics.
+ ///
+ /// `borrow_address` borrows this inner field
native public fun borrow_address(s: &signer): &address;
// Copies the address of the signer
diff --git a/third_party/move/move-stdlib/src/natives/bcs.rs b/third_party/move/move-stdlib/src/natives/bcs.rs
index c1722c0165fa1..3e9743e2018da 100644
--- a/third_party/move/move-stdlib/src/natives/bcs.rs
+++ b/third_party/move/move-stdlib/src/natives/bcs.rs
@@ -64,6 +64,7 @@ fn native_to_bytes(
// serialize value
let val = ref_to_val.read_ref()?;
let serialized_value = match ValueSerDeContext::new()
+ .with_legacy_signer()
.with_func_args_deserialization(context.function_value_extension())
.serialize(&val, &layout)?
{
diff --git a/third_party/move/move-stdlib/src/natives/signer.rs b/third_party/move/move-stdlib/src/natives/signer.rs
index 3a15343186a0c..90c8ccac06b48 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 addr = signer_reference.borrow_signer()?;
- Ok(NativeResult::ok(gas_params.base, smallvec![
- signer_reference.borrow_signer()?
- ]))
+ Ok(NativeResult::ok(gas_params.base, smallvec![addr]))
}
pub fn make_native_borrow_address(gas_params: BorrowAddressGasParameters) -> NativeFunction {
diff --git a/third_party/move/move-stdlib/src/natives/unit_test.rs b/third_party/move/move-stdlib/src/natives/unit_test.rs
index 31fe78d5490a7..2408e3001935c 100644
--- a/third_party/move/move-stdlib/src/natives/unit_test.rs
+++ b/third_party/move/move-stdlib/src/natives/unit_test.rs
@@ -45,7 +45,7 @@ fn native_create_signers_for_testing(
let num_signers = pop_arg!(args, u64);
let signers = Value::vector_for_testing_only(
- (0..num_signers).map(|i| Value::signer(AccountAddress::new(to_le_bytes(i)))),
+ (0..num_signers).map(|i| Value::master_signer(AccountAddress::new(to_le_bytes(i)))),
);
let cost = gas_params.base_cost + gas_params.unit_cost * NumArgs::new(num_signers);
diff --git a/third_party/move/move-vm/runtime/src/interpreter.rs b/third_party/move/move-vm/runtime/src/interpreter.rs
index 5950c9a08e5f6..03d6364edbb78 100644
--- a/third_party/move/move-vm/runtime/src/interpreter.rs
+++ b/third_party/move/move-vm/runtime/src/interpreter.rs
@@ -35,8 +35,8 @@ use move_vm_types::{
},
natives::function::NativeResult,
values::{
- self, GlobalValue, IntegerValue, Locals, Reference, Struct, StructRef, VMValueCast, Value,
- Vector, VectorRef,
+ self, GlobalValue, IntegerValue, Locals, Reference, SignerRef, Struct, StructRef,
+ VMValueCast, Value, Vector, VectorRef,
},
views::TypeView,
};
@@ -2163,9 +2163,9 @@ impl Frame {
},
Bytecode::MoveTo(sd_idx) => {
let resource = interpreter.operand_stack.pop()?;
- let signer_reference = interpreter.operand_stack.pop_as::()?;
+ let signer_reference = interpreter.operand_stack.pop_as::()?;
let addr = signer_reference
- .borrow_field(0)?
+ .borrow_signer()?
.value_as::()?
.read_ref()?
.value_as::()?;
@@ -2175,9 +2175,9 @@ impl Frame {
},
Bytecode::MoveToGeneric(si_idx) => {
let resource = interpreter.operand_stack.pop()?;
- let signer_reference = interpreter.operand_stack.pop_as::()?;
+ let signer_reference = interpreter.operand_stack.pop_as::()?;
let addr = signer_reference
- .borrow_field(0)?
+ .borrow_signer()?
.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..2c5ba78953a87 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 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/return_values.v2_exp b/third_party/move/move-vm/transactional-tests/tests/entry_points/return_values.v2_exp
index 13f10dcbdf982..207d694c94d44 100644
--- a/third_party/move/move-vm/transactional-tests/tests/entry_points/return_values.v2_exp
+++ b/third_party/move/move-vm/transactional-tests/tests/entry_points/return_values.v2_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/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 c8f390096f9ac..dd9c22140ad26 100644
--- a/third_party/move/move-vm/types/src/value_serde.rs
+++ b/third_party/move/move-vm/types/src/value_serde.rs
@@ -62,6 +62,7 @@ pub struct ValueSerDeContext<'a> {
#[allow(dead_code)]
pub(crate) function_extension: Option<&'a dyn FunctionValueExtension>,
pub(crate) delayed_fields_extension: Option>,
+ pub(crate) legacy_signer: bool,
}
impl<'a> ValueSerDeContext<'a> {
@@ -71,9 +72,16 @@ impl<'a> ValueSerDeContext<'a> {
Self {
function_extension: None,
delayed_fields_extension: None,
+ legacy_signer: false,
}
}
+ /// Serialize signer with legacy format to maintain backwards compatibility.
+ pub fn with_legacy_signer(mut self) -> Self {
+ self.legacy_signer = true;
+ self
+ }
+
/// Custom (de)serializer such that supports lookup of the argument types of a function during
/// function value deserialization.
pub fn with_func_args_deserialization(
@@ -89,6 +97,7 @@ impl<'a> ValueSerDeContext<'a> {
Self {
function_extension: self.function_extension,
delayed_fields_extension: None,
+ legacy_signer: self.legacy_signer,
}
}
diff --git a/third_party/move/move-vm/types/src/value_traversal.rs b/third_party/move/move-vm/types/src/value_traversal.rs
index 16a1669a6fe00..54cfac487e5bc 100644
--- a/third_party/move/move-vm/types/src/value_traversal.rs
+++ b/third_party/move/move-vm/types/src/value_traversal.rs
@@ -82,7 +82,7 @@ mod test {
#[test]
fn test_traversal_in_invalid_value() {
- let a = Value::signer_reference(AccountAddress::random());
+ let a = Value::master_signer_reference(AccountAddress::random());
assert_err!(find_identifiers_in_value(&a, &mut HashSet::new()));
}
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 e1c48c082fcbe..c2df063f767e1 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
@@ -216,7 +216,7 @@ fn test_serialized_size() {
(Value::u256(u256::U256::one()), U256),
(Value::bool(true), Bool),
(Value::address(AccountAddress::ONE), Address),
- (Value::signer(AccountAddress::ONE), Signer),
+ (Value::master_signer(AccountAddress::ONE), Signer),
(u64_delayed_value, Native(Aggregator, Box::new(U64))),
(u128_delayed_value, Native(Snapshot, Box::new(U128))),
(
@@ -261,3 +261,80 @@ fn test_serialized_size() {
.serialized_size(&value, &layout));
}
}
+
+#[test]
+fn new_signer_round_trip_vm_value() {
+ let move_value = MoveValue::Signer(AccountAddress::ZERO);
+ let bytes = move_value.simple_serialize().unwrap();
+
+ let vm_value = Value::master_signer(AccountAddress::ZERO);
+ let vm_bytes = ValueSerDeContext::new()
+ .serialize(&vm_value, &MoveTypeLayout::Signer)
+ .unwrap()
+ .unwrap();
+
+ // VM Value Roundtrip
+ assert!(ValueSerDeContext::new()
+ .deserialize(&vm_bytes, &MoveTypeLayout::Signer)
+ .unwrap()
+ .equals(&vm_value)
+ .unwrap());
+
+ // MoveValue Roundtrip
+ assert_eq!(
+ move_value,
+ MoveValue::simple_deserialize(&bytes, &MoveTypeLayout::Signer).unwrap()
+ );
+
+ // ser(MoveValue) == ser(VMValue)
+ assert_eq!(bytes, vm_bytes);
+
+ // Permissioned Signer Roundtrip
+ let vm_value = Value::permissioned_signer(AccountAddress::ZERO, AccountAddress::ONE);
+ let vm_bytes = ValueSerDeContext::new()
+ .serialize(&vm_value, &MoveTypeLayout::Signer)
+ .unwrap()
+ .unwrap();
+
+ // VM Value Roundtrip
+ assert!(ValueSerDeContext::new()
+ .deserialize(&vm_bytes, &MoveTypeLayout::Signer)
+ .unwrap()
+ .equals(&vm_value)
+ .unwrap());
+
+ // Cannot serialize permissioned signer into bytes with legacy signer
+ assert!(ValueSerDeContext::new()
+ .with_legacy_signer()
+ .serialize(&vm_value, &MoveTypeLayout::Signer)
+ .unwrap()
+ .is_none());
+}
+
+#[test]
+fn legacy_signer_round_trip_vm_value() {
+ let move_value = MoveValue::Address(AccountAddress::ZERO);
+ let bytes = move_value.simple_serialize().unwrap();
+
+ let vm_value = Value::master_signer(AccountAddress::ZERO);
+ let vm_bytes = ValueSerDeContext::new()
+ .with_legacy_signer()
+ .serialize(&vm_value, &MoveTypeLayout::Signer)
+ .unwrap()
+ .unwrap();
+
+ // VM Value Roundtrip
+ assert!(ValueSerDeContext::new()
+ .with_legacy_signer()
+ .deserialize(&vm_bytes, &MoveTypeLayout::Signer)
+ .is_none());
+
+ // MoveValue Roundtrip
+ assert_eq!(
+ move_value,
+ MoveValue::simple_deserialize(&bytes, &MoveTypeLayout::Address).unwrap()
+ );
+
+ // ser(MoveValue) == ser(VMValue)
+ assert_eq!(bytes, vm_bytes);
+}
diff --git a/third_party/move/move-vm/types/src/values/value_tests.rs b/third_party/move/move-vm/types/src/values/value_tests.rs
index c5d7574e774c4..1563c94df055d 100644
--- a/third_party/move/move-vm/types/src/values/value_tests.rs
+++ b/third_party/move/move-vm/types/src/values/value_tests.rs
@@ -251,8 +251,8 @@ fn test_mem_swap() -> PartialVMResult<()> {
// -- Container of container
locals.store_loc(8, Value::struct_(Struct::pack(vec![Value::u16(4)])), false)?;
locals.store_loc(9, Value::struct_(Struct::pack(vec![Value::u16(5)])), false)?;
- locals.store_loc(10, Value::signer(AccountAddress::ZERO), false)?;
- locals.store_loc(11, Value::signer(AccountAddress::ONE), false)?;
+ locals.store_loc(10, Value::master_signer(AccountAddress::ZERO), false)?;
+ locals.store_loc(11, Value::master_signer(AccountAddress::ONE), false)?;
// -- Container of vector
locals.store_loc(
@@ -267,12 +267,12 @@ fn test_mem_swap() -> PartialVMResult<()> {
)?;
locals.store_loc(
14,
- Value::vector_for_testing_only(vec![Value::signer(AccountAddress::ZERO)]),
+ Value::vector_for_testing_only(vec![Value::master_signer(AccountAddress::ZERO)]),
false,
)?;
locals.store_loc(
15,
- Value::vector_for_testing_only(vec![Value::signer(AccountAddress::ONE)]),
+ Value::vector_for_testing_only(vec![Value::master_signer(AccountAddress::ONE)]),
false,
)?;
@@ -334,8 +334,8 @@ mod native_values {
assert_err!(Value::u256(U256::zero()).equals(&v));
assert_err!(Value::address(AccountAddress::ONE).equals(&v));
- assert_err!(Value::signer(AccountAddress::ONE).equals(&v));
- assert_err!(Value::signer_reference(AccountAddress::ONE).equals(&v));
+ assert_err!(Value::master_signer(AccountAddress::ONE).equals(&v));
+ assert_err!(Value::master_signer_reference(AccountAddress::ONE).equals(&v));
assert_err!(Value::vector_bool(vec![true, false]).equals(&v));
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 fae84d1694a85..71ddeea856370 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
@@ -19,8 +19,11 @@ use move_core_types::{
account_address::AccountAddress,
effects::Op,
gas_algebra::AbstractMemorySize,
- u256, value,
- value::{MoveStruct, MoveStructLayout, MoveTypeLayout, MoveValue},
+ u256,
+ value::{
+ self, MoveStruct, MoveStructLayout, MoveTypeLayout, MoveValue, MASTER_ADDRESS_FIELD_OFFSET,
+ MASTER_SIGNER_VARIANT, PERMISSIONED_SIGNER_VARIANT, PERMISSION_ADDRESS_FIELD_OFFSET,
+ },
vm_status::{sub_status::NFE_VECTOR_ERROR_BASE, StatusCode},
};
use serde::{
@@ -290,8 +293,11 @@ impl Container {
}
}
- fn signer(x: AccountAddress) -> Self {
- Container::Struct(Rc::new(RefCell::new(vec![ValueImpl::Address(x)])))
+ fn master_signer(x: AccountAddress) -> Self {
+ Container::Struct(Rc::new(RefCell::new(vec![
+ ValueImpl::U16(MASTER_SIGNER_VARIANT),
+ ValueImpl::Address(x),
+ ])))
}
}
@@ -1513,7 +1519,39 @@ 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::()? == PERMISSIONED_SIGNER_VARIANT)
+ },
+ _ => Err(
+ PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR)
+ .with_message(format!("unexpected signer value: {:?}", self)),
+ ),
+ }
+ }
+
+ /// Get the permission address associated with a signer.
+ /// Needs to make sure the signer passed in is a permissioned signer.
+ pub fn permission_address(&self) -> PartialVMResult {
+ match &self.0 {
+ ContainerRef::Local(Container::Struct(s)) => Ok(Value::address(
+ *s.borrow()
+ .get(PERMISSION_ADDRESS_FIELD_OFFSET)
+ .ok_or_else(|| {
+ PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR)
+ .with_message(format!("unexpected signer value: {:?}", self))
+ })?
+ .as_value_ref::()?,
+ )),
+ _ => Err(
+ PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR)
+ .with_message(format!("unexpected signer value: {:?}", self)),
+ ),
+ }
}
}
@@ -1672,15 +1710,22 @@ impl Value {
Self(ValueImpl::Address(x))
}
- pub fn signer(x: AccountAddress) -> Self {
- Self(ValueImpl::Container(Container::signer(x)))
+ pub fn master_signer(x: AccountAddress) -> Self {
+ Self(ValueImpl::Container(Container::master_signer(x)))
+ }
+
+ pub fn permissioned_signer(x: AccountAddress, perm_storage_address: AccountAddress) -> Self {
+ Self::struct_(Struct::pack_variant(PERMISSIONED_SIGNER_VARIANT, 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 {
+ pub fn master_signer_reference(x: AccountAddress) -> Self {
Self(ValueImpl::ContainerRef(ContainerRef::Local(
- Container::signer(x),
+ Container::master_signer(x),
)))
}
@@ -3710,19 +3755,41 @@ impl<'c, 'l, 'v> 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.ctx.legacy_signer {
+ // Only allow serialization of master signer.
+ if *r.borrow()[0].as_value_ref::().map_err(|_| {
+ invariant_violation::(format!(
+ "First field of a signer needs to be an enum descriminator, got {:?}",
+ self.value
+ ))
+ })? != MASTER_SIGNER_VARIANT
+ {
+ return Err(S::Error::custom(PartialVMError::new(StatusCode::ABORTED)));
+ }
+ r.borrow()
+ .get(MASTER_ADDRESS_FIELD_OFFSET)
+ .ok_or_else(|| {
+ invariant_violation::(format!(
+ "cannot serialize container {:?} as {:?}",
+ self.value, self.layout
+ ))
+ })?
+ .as_value_ref::()
+ .map_err(|_| {
+ invariant_violation::(format!(
+ "cannot serialize container {:?} as {:?}",
+ self.value, self.layout
+ ))
+ })?
+ .serialize(serializer)
+ } else {
+ (SerializationReadyValue {
+ ctx: self.ctx,
+ layout: &MoveStructLayout::signer_serialization_layout(),
+ value: &*r.borrow(),
+ })
+ .serialize(serializer)
}
- (SerializationReadyValue {
- ctx: self.ctx,
- layout: &L::Address,
- value: &v[0],
- })
- .serialize(serializer)
},
// Delayed values. For their serialization, we must have custom
@@ -3874,7 +3941,19 @@ impl<'d, 'c> serde::de::DeserializeSeed<'d> for DeserializationSeed<'c, &MoveTyp
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 => {
+ if self.ctx.legacy_signer {
+ Err(D::Error::custom(
+ "Cannot deserialize signer into value".to_string(),
+ ))
+ } else {
+ let seed = DeserializationSeed {
+ ctx: self.ctx,
+ layout: &MoveStructLayout::signer_serialization_layout(),
+ };
+ Ok(Value::struct_(seed.deserialize(deserializer)?))
+ }
+ },
// Structs.
L::Struct(struct_layout) => {
@@ -4466,7 +4545,9 @@ pub mod prop {
L::U256 => any::().prop_map(Value::u256).boxed(),
L::Bool => any::().prop_map(Value::bool).boxed(),
L::Address => any::().prop_map(Value::address).boxed(),
- L::Signer => any::().prop_map(Value::signer).boxed(),
+ L::Signer => any::()
+ .prop_map(Value::master_signer)
+ .boxed(),
L::Vector(layout) => match &**layout {
L::U8 => vec(any::(), 0..10)
@@ -4660,10 +4741,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[MASTER_ADDRESS_FIELD_OFFSET] {
ValueImpl::Address(a) => MoveValue::Signer(*a),
v => panic!("Unexpected non-address while converting signer: {:?}", v),
}