Skip to content

Commit

Permalink
Implement rust logics for permissioned signer
Browse files Browse the repository at this point in the history
  • Loading branch information
runtian-zhou committed Sep 19, 2024
1 parent c7fcc0e commit 3ae6a87
Show file tree
Hide file tree
Showing 13 changed files with 250 additions and 30 deletions.
10 changes: 7 additions & 3 deletions aptos-move/e2e-move-tests/src/tests/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use aptos_types::{
transaction::{EntryFunction, TransactionPayload},
vm::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;
Expand All @@ -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(),
],
Expand All @@ -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();
Expand Down
5 changes: 5 additions & 0 deletions aptos-move/framework/src/natives/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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!(
Expand Down
103 changes: 103 additions & 0 deletions aptos-move/framework/src/natives/permissioned_signer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright © Aptos Foundation
// SPDX-License-Identifier: Apache-2.0
use aptos_native_interface::{
safely_pop_arg, RawSafeNative, SafeNativeBuilder, SafeNativeContext, SafeNativeError,
SafeNativeResult,
};
use move_vm_runtime::native_functions::NativeFunction;
use move_vm_types::{
loaded_data::runtime_types::Type,
values::{SignerRef, Struct, Value},
};
use move_core_types::account_address::AccountAddress;
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<Type>,
mut arguments: VecDeque<Value>,
) -> SafeNativeResult<SmallVec<[Value; 1]>> {
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<Type>,
mut arguments: VecDeque<Value>,
) -> SafeNativeResult<SmallVec<[Value; 1]>> {
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 });

Check warning on line 56 in aptos-move/framework/src/natives/permissioned_signer.rs

View check run for this annotation

Codecov / codecov/patch

aptos-move/framework/src/natives/permissioned_signer.rs#L56

Added line #L56 was not covered by tests
}

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<Type>,
mut arguments: VecDeque<Value>,
) -> SafeNativeResult<SmallVec<[Value; 1]>> {
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<Item = (String, NativeFunction)> + '_ {
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)
}
2 changes: 1 addition & 1 deletion aptos-move/framework/src/natives/string_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ fn native_format_impl(
let addr = if fix_enabled {
val.value_as::<Struct>()?
.unpack()?
.next()
.nth(1)
.unwrap()
.value_as::<AccountAddress>()?
} else {
Expand Down
9 changes: 8 additions & 1 deletion third_party/move/move-compiler-v2/src/plan_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) = &param;
let Parameter(var, ty, var_loc) = &param;

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)

Check warning on line 171 in third_party/move/move-compiler-v2/src/plan_builder.rs

View check run for this annotation

Codecov / codecov/patch

third_party/move/move-compiler-v2/src/plan_builder.rs#L170-L171

Added lines #L170 - L171 were not covered by tests
},
_ => MoveValue::Address(*addr),

Check warning on line 173 in third_party/move/move-compiler-v2/src/plan_builder.rs

View check run for this annotation

Codecov / codecov/patch

third_party/move/move-compiler-v2/src/plan_builder.rs#L173

Added line #L173 was not covered by tests
}),
Some(value) => arguments.push(value.clone()),
None => {
let missing_param_msg = "Missing test parameter assignment in test. Expected a \
Expand Down
16 changes: 13 additions & 3 deletions third_party/move/move-compiler/src/unit_test/plan_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -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!(
Expand Down
10 changes: 10 additions & 0 deletions third_party/move/move-core/types/src/unit_tests/value_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
);
}
19 changes: 17 additions & 2 deletions third_party/move/move-core/types/src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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")),

Check warning on line 488 in third_party/move/move-core/types/src/value.rs

View check run for this annotation

Codecov / codecov/patch

third_party/move/move-core/types/src/value.rs#L488

Added line #L488 was not covered by tests
}))
},
MoveTypeLayout::Struct(ty) => Ok(MoveValue::Struct(ty.deserialize(deserializer)?)),
MoveTypeLayout::Vector(layout) => Ok(MoveValue::Vector(
Expand Down Expand Up @@ -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 {
Expand Down
6 changes: 3 additions & 3 deletions third_party/move/move-stdlib/src/natives/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
4 changes: 2 additions & 2 deletions third_party/move/move-vm/runtime/src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2988,7 +2988,7 @@ impl Frame {
let resource = interpreter.operand_stack.pop()?;
let signer_reference = interpreter.operand_stack.pop_as::<StructRef>()?;
let addr = signer_reference
.borrow_field(0)?
.borrow_field(1)?
.value_as::<Reference>()?
.read_ref()?
.value_as::<AccountAddress>()?;
Expand All @@ -3008,7 +3008,7 @@ impl Frame {
let resource = interpreter.operand_stack.pop()?;
let signer_reference = interpreter.operand_stack.pop_as::<StructRef>()?;
let addr = signer_reference
.borrow_field(0)?
.borrow_field(1)?
.value_as::<Reference>()?
.read_ref()?
.value_as::<AccountAddress>()?;
Expand Down
5 changes: 5 additions & 0 deletions third_party/move/move-vm/types/src/value_serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ impl CustomSerializer for RelaxedCustomSerDe {
custom_serializer: None::<&RelaxedCustomSerDe>,
layout,
value: &value.0,
legacy_signer: false,

Check warning on line 107 in third_party/move/move-vm/types/src/value_serde.rs

View check run for this annotation

Codecov / codecov/patch

third_party/move/move-vm/types/src/value_serde.rs#L107

Added line #L107 was not covered by tests
}
.serialize(serializer)
}
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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!(
Expand Down Expand Up @@ -232,6 +235,7 @@ impl<'a, I: From<u64> + ExtractWidth + ExtractUniqueIndex> CustomSerializer
custom_serializer: None::<&RelaxedCustomSerDe>,
layout,
value: &value.0,
legacy_signer: false,

Check warning on line 238 in third_party/move/move-vm/types/src/value_serde.rs

View check run for this annotation

Codecov / codecov/patch

third_party/move/move-vm/types/src/value_serde.rs#L238

Added line #L238 was not covered by tests
}
.serialize(serializer)
}
Expand Down Expand Up @@ -291,6 +295,7 @@ pub fn serialize_and_replace_ids_with_values<I: From<u64> + ExtractWidth + Extra
custom_serializer: Some(&custom_serializer),
layout,
value: &value.0,
legacy_signer: false,

Check warning on line 298 in third_party/move/move-vm/types/src/value_serde.rs

View check run for this annotation

Codecov / codecov/patch

third_party/move/move-vm/types/src/value_serde.rs#L298

Added line #L298 was not covered by tests
};
bcs::to_bytes(&value).ok().filter(|_| {
// Should never happen, it should always fail first in serialize_and_allow_delayed_values
Expand Down
14 changes: 14 additions & 0 deletions third_party/move/move-vm/types/src/values/serialization_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
)
}
Loading

0 comments on commit 3ae6a87

Please sign in to comment.