Skip to content

add permissioned signer module and update existing modules to use dot… #211

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions crates/gas/src/initia_stdlib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ crate::macros::define_gas_parameters!(
[account_create_address_base_cost: InternalGas, "account.create_address.base", 1102],
[account_create_signer_base_cost: InternalGas, "account.create_signer.base", 1102],

[permission_address_base: InternalGas, "permissioned_signer.permission_address.base", 1102],
[is_permissioned_signer_base: InternalGas, "permissioned_signer.is_permissioned_signer.base", 1102],
[signer_from_permissioned_handle_base: InternalGas, "permissioned_signer.signer_from_permissioned_handle.base", 1102],

[address_to_string_base_cost: InternalGas, "address.to_string.base_cost", 1678], // 1102 + 18 * 32
[address_from_string_base_cost: InternalGas, "address.from_string.base_cost", 1102],
[address_from_string_per_byte: InternalGasPerByte, "address.from_string.per_byte", 18],
Expand Down
2 changes: 1 addition & 1 deletion crates/gas/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub use meter::{
pub use misc::{AbstractValueSizeGasParameters, MiscGasParameters};
pub use move_core_types::gas_algebra::{
Arg, Byte, GasQuantity, InternalGas, InternalGasPerArg, InternalGasPerByte, InternalGasUnit,
NumArgs, NumBytes, UnitDiv,
NumArgs, NumBytes, UnitDiv
};
pub use traits::{FromOnChainGasSchedule, InitialGasSchedule, ToOnChainGasSchedule};

Expand Down
13 changes: 12 additions & 1 deletion crates/gas/src/move_stdlib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use move_core_types::gas_algebra::{InternalGas, InternalGasPerByte};
use move_core_types::gas_algebra::{InternalGas, InternalGasPerArg, InternalGasPerByte, InternalGasPerTypeNode};
use crate::InternalGasPerAbstractValueUnit;

crate::macros::define_gas_parameters!(
MoveStdlibGasParameters,
Expand All @@ -11,6 +12,8 @@ crate::macros::define_gas_parameters!(
[bcs_serialized_size_base: InternalGas, "bcs.serialized_size.base", 735],
[bcs_serialized_size_per_byte_serialized: InternalGasPerByte, "bcs.serialized_size.per_byte_serialized", 36],
[bcs_serialized_size_failure: InternalGas, "bcs.serialized_size.failure", 3676],
[bcs_constant_serialized_size_base: InternalGas, "bcs.constant_serialized_size.base", 735],
[bcs_constant_serialized_size_per_type_node: InternalGasPerTypeNode, "bcs.constant_serialized_size.per_type_node", 40],

[hash_sha2_256_base: InternalGas, "hash.sha2_256.base", 11028],
[hash_sha2_256_per_byte: InternalGasPerByte, "hash.sha2_256.per_byte", 183],
Expand All @@ -31,5 +34,13 @@ crate::macros::define_gas_parameters!(
[string_index_of_base: InternalGas, "string.index_of.base", 1470],
[string_index_of_per_byte_pattern: InternalGasPerByte, "string.index_of.per_byte_pattern", 73],
[string_index_of_per_byte_searched: InternalGasPerByte, "string.index_of.per_byte_searched", 36],

[cmp_compare_base: InternalGas, "cmp.compare.base", 367],
[cmp_compare_per_abs_val_unit: InternalGasPerAbstractValueUnit, "cmp.compare.per_abs_val_unit", 14],

[vector_move_range_base: InternalGas, "vector.move_range.base", 4000],
[vector_move_range_per_index_moved: InternalGasPerArg, "vector.move_range.per_index_moved", 10],

[mem_swap_base: InternalGas, "mem.swap.base", 1500],
]
);
4 changes: 4 additions & 0 deletions crates/natives/src/interface/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ impl SafeNativeContext<'_, '_, '_> {
self.misc_gas_params.abs_val.abstract_value_size(val)
}

pub fn abs_val_size_dereferenced(&self, val: &Value) -> AbstractValueSize {
self.misc_gas_params.abs_val.abstract_value_size_dereferenced(val)
}

/// Computes left gas balance for this native context.
pub fn gas_balance(&self) -> InternalGas {
self.gas_budget.checked_sub(self.gas_used).unwrap()
Expand Down
3 changes: 3 additions & 0 deletions crates/natives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub mod keccak;
pub mod move_stdlib;
pub mod object;
pub mod oracle;
pub mod permissioned_signer;
pub mod query;
pub mod staking;
pub mod string_utils;
Expand Down Expand Up @@ -86,6 +87,8 @@ pub fn initia_move_natives(
);
add_natives_from_module!("biguint", biguint::make_all(builder));

add_natives_from_module!("permissioned_signer", permissioned_signer::make_all(builder));

#[cfg(feature = "testing")]
add_natives_from_module!("ibctesting", ibctesting::make_all(builder));

Expand Down
124 changes: 114 additions & 10 deletions crates/natives/src/move_stdlib/bcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
// Copyright (c) The Move Contributors
// SPDX-License-Identifier: Apache-2.0

use move_core_types::gas_algebra::NumBytes;
use move_binary_format::errors::PartialVMError;
use move_core_types::{account_address::AccountAddress, gas_algebra::{NumBytes, NumTypeNodes}, u256, value::{MoveStructLayout, MoveTypeLayout}, vm_status::{sub_status::NFE_BCS_SERIALIZATION_FAILURE, StatusCode}};
use move_vm_runtime::native_functions::NativeFunction;
use move_vm_types::{
loaded_data::runtime_types::Type,
natives::function::PartialVMResult,
value_serde::ValueSerDeContext,
values::{values_impl::Reference, Value},
values::{values_impl::Reference, Struct, Value},
};
use smallvec::{smallvec, SmallVec};
use std::collections::VecDeque;
Expand All @@ -22,11 +23,9 @@ use crate::{
safely_pop_arg,
};

// See stdlib/error.move
const ECATEGORY_INVALID_ARGUMENT: u64 = 0x1;

// native errors always start from 100
const BCS_SERIALIZATION_FAILURE: u64 = (ECATEGORY_INVALID_ARGUMENT << 16) + 100;
pub fn create_option_u64(value: Option<u64>) -> Value {
Value::struct_(Struct::pack(vec![Value::vector_u64(value)]))
}

/***************************************************************************************************
* native fun to_bytes
Expand Down Expand Up @@ -62,7 +61,7 @@ fn native_to_bytes(
Err(_) => {
context.charge(gas_params.bcs_to_bytes_failure)?;
return Err(SafeNativeError::Abort {
abort_code: BCS_SERIALIZATION_FAILURE,
abort_code: NFE_BCS_SERIALIZATION_FAILURE,
});
}
};
Expand All @@ -80,7 +79,7 @@ fn native_to_bytes(
None => {
context.charge(gas_params.bcs_to_bytes_failure)?;
return Err(SafeNativeError::Abort {
abort_code: BCS_SERIALIZATION_FAILURE,
abort_code: NFE_BCS_SERIALIZATION_FAILURE,
});
}
};
Expand Down Expand Up @@ -123,7 +122,7 @@ fn native_serialized_size(

// Reuse the same abort code as bcs::to_bytes.
return Err(SafeNativeError::Abort {
abort_code: BCS_SERIALIZATION_FAILURE,
abort_code: NFE_BCS_SERIALIZATION_FAILURE,
});
}
};
Expand Down Expand Up @@ -152,6 +151,110 @@ fn serialized_size_impl(
.serialized_size(&value, &ty_layout)
}

fn native_constant_serialized_size(
context: &mut SafeNativeContext,
mut ty_args: Vec<Type>,
_args: VecDeque<Value>,
) -> SafeNativeResult<SmallVec<[Value; 1]>> {
debug_assert!(ty_args.len() == 1);

let gas_params = &context.native_gas_params.move_stdlib;

context.charge(gas_params.bcs_constant_serialized_size_base)?;

let ty = ty_args.pop().unwrap();
let ty_layout = context.type_to_type_layout(&ty)?;

let (visited_count, serialized_size_result) = constant_serialized_size(&ty_layout);
context
.charge(gas_params.bcs_constant_serialized_size_per_type_node * NumTypeNodes::new(visited_count))?;

let result = match serialized_size_result {
Ok(value) => create_option_u64(value.map(|v| v as u64)),
Err(_) => {
context.charge(gas_params.bcs_serialized_size_failure)?;

// Re-use the same abort code as bcs::to_bytes.
return Err(SafeNativeError::Abort {
abort_code: NFE_BCS_SERIALIZATION_FAILURE,
});
},
};

Ok(smallvec![result])
}

/// If given type has a constant serialized size (irrespective of the instance), it returns the serialized
/// size in bytes any value would have.
/// Otherwise it returns None.
/// First element of the returned tuple represents number of visited nodes, used to charge gas.
fn constant_serialized_size(ty_layout: &MoveTypeLayout) -> (u64, PartialVMResult<Option<usize>>) {
let mut visited_count = 1;
let bcs_size_result = match ty_layout {
MoveTypeLayout::Bool => bcs::serialized_size(&false).map(Some),
MoveTypeLayout::U8 => bcs::serialized_size(&0u8).map(Some),
MoveTypeLayout::U16 => bcs::serialized_size(&0u16).map(Some),
MoveTypeLayout::U32 => bcs::serialized_size(&0u32).map(Some),
MoveTypeLayout::U64 => bcs::serialized_size(&0u64).map(Some),
MoveTypeLayout::U128 => bcs::serialized_size(&0u128).map(Some),
MoveTypeLayout::U256 => bcs::serialized_size(&u256::U256::zero()).map(Some),
MoveTypeLayout::Address => bcs::serialized_size(&AccountAddress::ZERO).map(Some),
// signer's size is VM implementation detail, and can change at will.
MoveTypeLayout::Signer => Ok(None),
// vectors have no constant size
MoveTypeLayout::Vector(_) => Ok(None),
// enums and functions have no constant size
MoveTypeLayout::Struct(
MoveStructLayout::RuntimeVariants(_) | MoveStructLayout::WithVariants(_),
)
| MoveTypeLayout::Function(..) => Ok(None),
MoveTypeLayout::Struct(MoveStructLayout::Runtime(fields)) => {
let mut total = Some(0);
for field in fields {
let (cur_visited_count, cur) = constant_serialized_size(field);
visited_count += cur_visited_count;
match cur {
Err(e) => return (visited_count, Err(e)),
Ok(Some(cur_value)) => total = total.map(|v| v + cur_value),
Ok(None) => {
total = None;
break;
},
}
}
Ok(total)
},
MoveTypeLayout::Struct(MoveStructLayout::WithFields(_))
| MoveTypeLayout::Struct(MoveStructLayout::WithTypes { .. }) => {
return (
visited_count,
Err(
PartialVMError::new(StatusCode::VALUE_SERIALIZATION_ERROR).with_message(
"Only runtime types expected, but found WithFields/WithTypes".to_string(),
),
),
)
},
MoveTypeLayout::Native(_, inner) => {
let (cur_visited_count, cur) = constant_serialized_size(inner);
visited_count += cur_visited_count;
match cur {
Err(e) => return (visited_count, Err(e)),
Ok(v) => Ok(v),
}
},
};
(
visited_count,
bcs_size_result.map_err(|e| {
PartialVMError::new(StatusCode::VALUE_SERIALIZATION_ERROR).with_message(format!(
"failed to compute serialized size of a value: {:?}",
e
))
}),
)
}

/***************************************************************************************************
* module
**************************************************************************************************/
Expand All @@ -161,6 +264,7 @@ pub fn make_all(
let funcs = [
("to_bytes", native_to_bytes as RawSafeNative),
("serialized_size", native_serialized_size),
("constant_serialized_size", native_constant_serialized_size),
];

builder.make_named_natives(funcs)
Expand Down
74 changes: 74 additions & 0 deletions crates/natives/src/move_stdlib/cmp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright © Aptos Foundation
// SPDX-License-Identifier: Apache-2.0

// Copyright (c) The Diem Core Contributors
// Copyright (c) The Move Contributors
// SPDX-License-Identifier: Apache-2.0

//! Implementation of native functions for value comparison.

use crate::interface::{
RawSafeNative, SafeNativeBuilder, SafeNativeContext, SafeNativeError, SafeNativeResult,
};
use move_core_types::vm_status::StatusCode;
use move_vm_runtime::native_functions::NativeFunction;
use move_vm_types::{
loaded_data::runtime_types::Type,
natives::function::PartialVMError,
values::{Struct, Value},
};
use smallvec::{smallvec, SmallVec};
use std::collections::VecDeque;

const ORDERING_LESS_THAN_VARIANT: u16 = 0;
const ORDERING_EQUAL_VARIANT: u16 = 1;
const ORDERING_GREATER_THAN_VARIANT: u16 = 2;

/***************************************************************************************************
* native fun native_compare
*
* gas cost: CMP_COMPARE_BASE + CMP_COMPARE_PER_ABS_VAL_UNIT * dereferenced_size_of_both_values
*
**************************************************************************************************/
fn native_compare(
context: &mut SafeNativeContext,
_ty_args: Vec<Type>,
args: VecDeque<Value>,
) -> SafeNativeResult<SmallVec<[Value; 1]>> {
debug_assert!(args.len() == 2);
let gas_params = &context.native_gas_params.move_stdlib;

if args.len() != 2 {
return Err(SafeNativeError::InvariantViolation(PartialVMError::new(
StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR,
)));
}

let cost = gas_params.cmp_compare_base
+ gas_params.cmp_compare_per_abs_val_unit
* (context.abs_val_size_dereferenced(&args[0])
+ context.abs_val_size_dereferenced(&args[1]));
context.charge(cost)?;

let ordering = args[0].compare(&args[1])?;
let ordering_move_variant = match ordering {
std::cmp::Ordering::Less => ORDERING_LESS_THAN_VARIANT,
std::cmp::Ordering::Equal => ORDERING_EQUAL_VARIANT,
std::cmp::Ordering::Greater => ORDERING_GREATER_THAN_VARIANT,
};
Comment on lines +47 to +58
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

& references are off by one level – will not compile

VecDeque::index returns &Value.
Passing &args[0] therefore yields &&Value. The same applies to &args[1].

-            * (context.abs_val_size_dereferenced(&args[0])
-                + context.abs_val_size_dereferenced(&args[1]));
+            * (context.abs_val_size_dereferenced(args.get(0).unwrap())
+                + context.abs_val_size_dereferenced(args.get(1).unwrap()));-    let ordering = args[0].compare(&args[1])?;
+    let ordering = args.get(0).unwrap().compare(args.get(1).unwrap())?;

Without this fix the crate will fail to compile with a “mismatched types: expected &Value, found &&Value” error.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let cost = gas_params.cmp_compare_base
+ gas_params.cmp_compare_per_abs_val_unit
* (context.abs_val_size_dereferenced(&args[0])
+ context.abs_val_size_dereferenced(&args[1]));
context.charge(cost)?;
let ordering = args[0].compare(&args[1])?;
let ordering_move_variant = match ordering {
std::cmp::Ordering::Less => ORDERING_LESS_THAN_VARIANT,
std::cmp::Ordering::Equal => ORDERING_EQUAL_VARIANT,
std::cmp::Ordering::Greater => ORDERING_GREATER_THAN_VARIANT,
};
let cost = gas_params.cmp_compare_base
+ gas_params.cmp_compare_per_abs_val_unit
* (context.abs_val_size_dereferenced(args.get(0).unwrap())
+ context.abs_val_size_dereferenced(args.get(1).unwrap()));
context.charge(cost)?;
let ordering = args.get(0).unwrap().compare(args.get(1).unwrap())?;
let ordering_move_variant = match ordering {
std::cmp::Ordering::Less => ORDERING_LESS_THAN_VARIANT,
std::cmp::Ordering::Equal => ORDERING_EQUAL_VARIANT,
std::cmp::Ordering::Greater => ORDERING_GREATER_THAN_VARIANT,
};
🤖 Prompt for AI Agents
In crates/natives/src/move_stdlib/cmp.rs around lines 47 to 58, the code
incorrectly takes references of args elements which are already references,
resulting in &&Value instead of &Value. To fix this, remove the extra &
operators before args[0] and args[1] when passing them to functions expecting
&Value, ensuring the types match and the code compiles correctly.


Ok(smallvec![Value::struct_(Struct::pack(vec![Value::u16(
ordering_move_variant
)]))])
}

/***************************************************************************************************
* module
**************************************************************************************************/
pub fn make_all(
builder: &SafeNativeBuilder,
) -> impl Iterator<Item = (String, NativeFunction)> + '_ {
let natives = [("compare", native_compare as RawSafeNative)];

builder.make_named_natives(natives)
}
53 changes: 53 additions & 0 deletions crates/natives/src/move_stdlib/mem.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright © Aptos Foundation
// SPDX-License-Identifier: Apache-2.0

//! Implementation of native functions for memory manipulation.

use crate::{interface::{
RawSafeNative, SafeNativeBuilder, SafeNativeContext,
SafeNativeResult,
}, safely_pop_arg};
use move_vm_runtime::native_functions::NativeFunction;
use move_vm_types::{
loaded_data::runtime_types::Type,
values::{Reference, Value},
};
use smallvec::{smallvec, SmallVec};
use std::collections::VecDeque;


/***************************************************************************************************
* native fun native_swap
*
* gas cost: MEM_SWAP_BASE
*
**************************************************************************************************/
fn native_swap(
context: &mut SafeNativeContext,
_ty_args: Vec<Type>,
mut args: VecDeque<Value>,
) -> SafeNativeResult<SmallVec<[Value; 1]>> {
let gas_params = &context.native_gas_params.move_stdlib;

debug_assert!(args.len() == 2);

context.charge(gas_params.mem_swap_base)?;

let left = safely_pop_arg!(args, Reference);
let right = safely_pop_arg!(args, Reference);

left.swap_values(right)?;

Ok(smallvec![])
}

/***************************************************************************************************
* module
**************************************************************************************************/
pub fn make_all(
builder: &SafeNativeBuilder,
) -> impl Iterator<Item = (String, NativeFunction)> + '_ {
let natives = [("swap", native_swap as RawSafeNative)];

builder.make_named_natives(natives)
}
Loading
Loading