diff --git a/aptos-move/framework/move-stdlib/src/natives/bcs.rs b/aptos-move/framework/move-stdlib/src/natives/bcs.rs
index 48a058650b938..1ba7a7f17ca3f 100644
--- a/aptos-move/framework/move-stdlib/src/natives/bcs.rs
+++ b/aptos-move/framework/move-stdlib/src/natives/bcs.rs
@@ -146,12 +146,11 @@ fn native_constant_serialized_size(
let ty = ty_args.pop().unwrap();
let ty_layout = context.type_to_type_layout(&ty)?;
- context.charge(
- BCS_CONSTANT_SERIALIZED_SIZE_PER_TYPE_NODE
- * NumTypeNodes::new(type_visit_count_for_constant_serialized_size(&ty_layout)),
- )?;
+ let (visited_count, serialized_size_result) = constant_serialized_size(&ty_layout);
+ context
+ .charge(BCS_CONSTANT_SERIALIZED_SIZE_PER_TYPE_NODE * NumTypeNodes::new(visited_count))?;
- let result = match constant_serialized_size(&ty_layout) {
+ let result = match serialized_size_result {
Ok(value) => create_option_u64(value.map(|v| v as u64)),
Err(_) => {
context.charge(BCS_SERIALIZED_SIZE_FAILURE)?;
@@ -166,57 +165,12 @@ fn native_constant_serialized_size(
Ok(smallvec![result])
}
-/// Count upper limit on the number of types constant_serialized_size would visit,
-/// which is then used for gas charging, before performing the operation.
-/// This is different done type.num_nodes(), as some types are not traversed (i.e. vector),
-/// and for structs types and number of fields matter as well.
-///
-/// Unclear if type_visit_count would be the same for other usages
-/// (for example, whether vector types need to be traversed),
-/// so name it very specifically, and on future usages see how it generalizes.
-fn type_visit_count_for_constant_serialized_size(ty_layout: &MoveTypeLayout) -> u64 {
- match ty_layout {
- MoveTypeLayout::Bool
- | MoveTypeLayout::U8
- | MoveTypeLayout::U16
- | MoveTypeLayout::U32
- | MoveTypeLayout::U128
- | MoveTypeLayout::U256
- | MoveTypeLayout::U64
- | MoveTypeLayout::Address
- | MoveTypeLayout::Signer => 1,
- // non-recursed:
- MoveTypeLayout::Struct(
- MoveStructLayout::RuntimeVariants(_) | MoveStructLayout::WithVariants(_),
- )
- | MoveTypeLayout::Vector(_) => 1,
- // recursed:
- MoveTypeLayout::Struct(MoveStructLayout::Runtime(fields)) => {
- let mut total = 1; // Count the current visit, and aggregate all children
- for field in fields {
- total += type_visit_count_for_constant_serialized_size(field);
- }
- total
- },
- MoveTypeLayout::Struct(MoveStructLayout::WithFields(fields))
- | MoveTypeLayout::Struct(MoveStructLayout::WithTypes { fields, .. }) => {
- let mut total = 1; // Count the current visit, and aggregate all children
- for field in fields {
- total += type_visit_count_for_constant_serialized_size(&field.layout);
- }
- total
- },
- // Count the current visit, and inner visits
- MoveTypeLayout::Native(_, inner) => {
- 1 + type_visit_count_for_constant_serialized_size(inner)
- },
- }
-}
-
/// 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.
-fn constant_serialized_size(ty_layout: &MoveTypeLayout) -> PartialVMResult