Skip to content

Commit

Permalink
[Move] Box type layout vectors (#19310)
Browse files Browse the repository at this point in the history
## Description 

Boxes fields in the `MoveTypeLayout` to make the enum size smaller for
type layouts.

## Test plan 

Added test to check size of the enums + make sure existing tests pass. 

---

## Release notes

Check each box that your changes affect. If none of the boxes relate to
your changes, release notes aren't required.

For each box you select, include information after the relevant heading
that describes the impact of your changes that a user might notice and
any actions they must take to implement updates.

- [X] Protocol: Increase the maximum type layout size in the VM. Most
users should not notice this change.
- [ ] Nodes (Validators and Full nodes): 
- [ ] Indexer: 
- [ ] JSON-RPC: 
- [ ] GraphQL: 
- [ ] CLI: 
- [ ] Rust SDK:
- [ ] REST API:
  • Loading branch information
tzakian authored and suiwombat committed Sep 16, 2024
1 parent 517fd81 commit 7e3789a
Show file tree
Hide file tree
Showing 41 changed files with 335 additions and 206 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ gas summary: computation_cost: 1000000, storage_cost: 988000, storage_rebate: 0
task 3, lines 40-41:
//# programmable --sender A
//> test::m::x3()
Error: Transaction Effects Status: Move Bytecode Verification Error. Please run the Bytecode Verifier for more information.
Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: VMVerificationOrDeserializationError, source: Some(VMError { major_status: TOO_MANY_TYPE_NODES, sub_status: None, message: None, exec_state: None, location: Undefined, indices: [], offsets: [] }), command: Some(0) } }
mutated: object(0,0)
gas summary: computation_cost: 1000000, storage_cost: 988000, storage_rebate: 978120, non_refundable_storage_fee: 9880
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
processed 4 tasks

init:
A: object(0,0)

task 1, lines 8-35:
//# publish
created: object(1,0)
mutated: object(0,1)
gas summary: computation_cost: 1000000, storage_cost: 6452400, storage_rebate: 0, non_refundable_storage_fee: 0

task 2, lines 37-38:
//# programmable --sender A
//> test::m::x1()
mutated: object(0,0)
gas summary: computation_cost: 1000000, storage_cost: 988000, storage_rebate: 0, non_refundable_storage_fee: 0

task 3, lines 40-41:
//# programmable --sender A
//> test::m::x3()
Error: Transaction Effects Status: Move Bytecode Verification Error. Please run the Bytecode Verifier for more information.
Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: VMVerificationOrDeserializationError, source: Some(VMError { major_status: TOO_MANY_TYPE_NODES, sub_status: None, message: None, exec_state: None, location: Undefined, indices: [], offsets: [] }), command: Some(0) } }
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

// tests error after serializing a large enum return value

//# init --addresses test=0x0 --accounts A --protocol-version 58

//# publish

module test::m {

public enum X1 has drop {
Big1(u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8),
}

public enum X2 has drop {
V1(X1, X1, X1),
V2(X1, X1, X1),
V3(X1, X1, X1),
}

public enum X3 has drop {
X2(X2, X2, X2),
U64(u64),
}

entry fun x1(): X1 {
X1::Big1(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
}

entry fun x3(): X3 {
X3::U64(0)
}

}

//# programmable --sender A
//> test::m::x1()

//# programmable --sender A
//> test::m::x3()
14 changes: 8 additions & 6 deletions crates/sui-core/src/unit_tests/subscription_handler_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,21 +85,23 @@ impl TestEvent {
fn layout() -> MoveStructLayout {
MoveStructLayout {
type_: Self::type_(),
fields: vec![
fields: Box::new(vec![
MoveFieldLayout::new(ident_str!("creator").to_owned(), MoveTypeLayout::Address),
MoveFieldLayout::new(
ident_str!("name").to_owned(),
MoveTypeLayout::Struct(UTF8String::layout()),
MoveTypeLayout::Struct(Box::new(UTF8String::layout())),
),
MoveFieldLayout::new(
ident_str!("data").to_owned(),
MoveTypeLayout::Vector(Box::new(MoveTypeLayout::U64)),
),
MoveFieldLayout::new(
ident_str!("coins").to_owned(),
MoveTypeLayout::Vector(Box::new(MoveTypeLayout::Struct(GasCoin::layout()))),
MoveTypeLayout::Vector(Box::new(MoveTypeLayout::Struct(Box::new(
GasCoin::layout(),
)))),
),
],
]),
}
}
}
Expand Down Expand Up @@ -131,10 +133,10 @@ impl UTF8String {
fn layout() -> MoveStructLayout {
MoveStructLayout {
type_: Self::type_(),
fields: vec![MoveFieldLayout::new(
fields: Box::new(vec![MoveFieldLayout::new(
ident_str!("bytes").to_owned(),
MoveTypeLayout::Vector(Box::new(MoveTypeLayout::U8)),
)],
)]),
}
}
}
4 changes: 2 additions & 2 deletions crates/sui-graphql-rpc/src/types/move_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,8 @@ impl TryFrom<A::MoveTypeLayout> for MoveTypeLayout {
TL::Address => Self::Address,

TL::Vector(v) => Self::Vector(Box::new(Self::try_from(*v)?)),
TL::Struct(s) => Self::Struct(s.try_into()?),
TL::Enum(e) => Self::Enum(e.try_into()?),
TL::Struct(s) => Self::Struct((*s).try_into()?),
TL::Enum(e) => Self::Enum((*e).try_into()?),
})
}
}
Expand Down
8 changes: 4 additions & 4 deletions crates/sui-graphql-rpc/src/types/move_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,13 +474,13 @@ mod tests {

macro_rules! struct_layout {
($type:literal { $($name:literal : $layout:expr),* $(,)?}) => {
A::MoveTypeLayout::Struct(S {
A::MoveTypeLayout::Struct(Box::new(S {
type_: StructTag::from_str($type).expect("Failed to parse struct"),
fields: vec![$(MoveFieldLayout {
fields: Box::new(vec![$(MoveFieldLayout {
name: ident_str!($name).to_owned(),
layout: $layout,
}),*]
})
}),*])
}))
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/sui-indexer/src/handlers/checkpoint_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -709,7 +709,7 @@ async fn get_move_struct_layout_map(
move_core_types::annotated_value::MoveStructLayout,
),
IndexerError,
>((struct_tag, move_struct_layout))
>((struct_tag, *move_struct_layout))
}
})
.collect::<Vec<_>>();
Expand Down
2 changes: 1 addition & 1 deletion crates/sui-indexer/src/models/objects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ impl StoredObject {
)),
}?;

Ok(ObjectRead::Exists(oref, object, Some(move_struct_layout)))
Ok(ObjectRead::Exists(oref, object, Some(*move_struct_layout)))
}

pub fn get_object_ref(&self) -> Result<ObjectRef, IndexerError> {
Expand Down
55 changes: 26 additions & 29 deletions crates/sui-json/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ impl SuiJsonValue {
with one field of address or u8 vector type"
),
},
MoveTypeLayout::Struct(MoveStructLayout { type_, .. }) if type_ == &ID::type_() => {
MoveTypeLayout::Struct(struct_layout) if struct_layout.type_ == ID::type_() => {
Ok(R::MoveValue::Struct(R::MoveStruct(vec![
Self::to_move_value(val, &inner_vec[0].layout.clone())?,
])))
Expand Down Expand Up @@ -277,27 +277,26 @@ impl SuiJsonValue {
R::MoveValue::U256(convert_string_to_u256(s.as_str())?)
}
// For ascii and utf8 strings
(
JsonValue::String(s),
MoveTypeLayout::Struct(MoveStructLayout { type_, fields: _ }),
) if is_move_string_type(type_) => {
(JsonValue::String(s), MoveTypeLayout::Struct(struct_layout))
if is_move_string_type(&struct_layout.type_) =>
{
R::MoveValue::Vector(s.as_bytes().iter().copied().map(R::MoveValue::U8).collect())
}
// For ID
(JsonValue::String(s), MoveTypeLayout::Struct(MoveStructLayout { type_, fields }))
if type_ == &ID::type_() =>
(JsonValue::String(s), MoveTypeLayout::Struct(struct_layout))
if struct_layout.type_ == ID::type_() =>
{
if fields.len() != 1 {
if struct_layout.fields.len() != 1 {
bail!(
"Cannot convert string arg {s} to {type_} which is expected to be a struct with one field"
"Cannot convert string arg {s} to {} which is expected to be a struct with one field", struct_layout.type_
);
};
let addr = SuiAddress::from_str(s)?;
R::MoveValue::Address(addr.into())
}
(JsonValue::Object(o), MoveTypeLayout::Struct(MoveStructLayout { fields, .. })) => {
(JsonValue::Object(o), MoveTypeLayout::Struct(struct_layout)) => {
let mut field_values = vec![];
for layout in fields {
for layout in struct_layout.fields.iter() {
let field = o
.get(layout.name.as_str())
.ok_or_else(|| anyhow!("Missing field {} for struct {ty}", layout.name))?;
Expand All @@ -306,10 +305,8 @@ impl SuiJsonValue {
R::MoveValue::Struct(R::MoveStruct(field_values))
}
// Unnest fields
(value, MoveTypeLayout::Struct(MoveStructLayout { fields, .. }))
if fields.len() == 1 =>
{
Self::to_move_value(value, &fields[0].layout)?
(value, MoveTypeLayout::Struct(struct_layout)) if struct_layout.fields.len() == 1 => {
Self::to_move_value(value, &struct_layout.fields[0].layout)?
}
(JsonValue::String(s), MoveTypeLayout::Vector(t)) => {
match &**t {
Expand All @@ -332,8 +329,8 @@ impl SuiJsonValue {
};
R::MoveValue::Vector(vec.iter().copied().map(R::MoveValue::U8).collect())
}
MoveTypeLayout::Struct(MoveStructLayout { fields: inner, .. }) => {
Self::handle_inner_struct_layout(inner, val, ty, s)?
MoveTypeLayout::Struct(struct_layout) => {
Self::handle_inner_struct_layout(&struct_layout.fields, val, ty, s)?
}
_ => bail!("Cannot convert string arg {s} to {ty}"),
}
Expand Down Expand Up @@ -594,36 +591,36 @@ pub fn primitive_type(
if resolved_struct == RESOLVED_ASCII_STR {
(
true,
Some(MoveTypeLayout::Struct(MoveStructLayout {
Some(MoveTypeLayout::Struct(Box::new(MoveStructLayout {
type_: resolved_to_struct(RESOLVED_ASCII_STR),
fields: vec![MoveFieldLayout::new(
fields: Box::new(vec![MoveFieldLayout::new(
ident_str!("bytes").into(),
MoveTypeLayout::Vector(Box::new(MoveTypeLayout::U8)),
)],
})),
)]),
}))),
)
} else if resolved_struct == RESOLVED_UTF8_STR {
// both structs structs representing strings have one field - a vector of type u8
(
true,
Some(MoveTypeLayout::Struct(MoveStructLayout {
Some(MoveTypeLayout::Struct(Box::new(MoveStructLayout {
type_: resolved_to_struct(RESOLVED_UTF8_STR),
fields: vec![MoveFieldLayout::new(
fields: Box::new(vec![MoveFieldLayout::new(
ident_str!("bytes").into(),
MoveTypeLayout::Vector(Box::new(MoveTypeLayout::U8)),
)],
})),
)]),
}))),
)
} else if resolved_struct == RESOLVED_SUI_ID {
(
true,
Some(MoveTypeLayout::Struct(MoveStructLayout {
Some(MoveTypeLayout::Struct(Box::new(MoveStructLayout {
type_: resolved_to_struct(RESOLVED_SUI_ID),
fields: vec![MoveFieldLayout::new(
fields: Box::new(vec![MoveFieldLayout::new(
ident_str!("bytes").into(),
MoveTypeLayout::Address,
)],
})),
)]),
}))),
)
} else {
(false, None)
Expand Down
Loading

0 comments on commit 7e3789a

Please sign in to comment.