diff --git a/Cargo.lock b/Cargo.lock index 8c8215cb2e..d9c7c27457 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5171,6 +5171,7 @@ dependencies = [ "move-bytecode-utils", "move-core-types", "move-resource-viewer", + "move-vm-types", "once_cell", "primitive-types 0.12.1", "proptest", diff --git a/crates/rooch-rpc-api/src/jsonrpc_types/move_types.rs b/crates/rooch-rpc-api/src/jsonrpc_types/move_types.rs index f01420e2ae..9ef27647fa 100644 --- a/crates/rooch-rpc-api/src/jsonrpc_types/move_types.rs +++ b/crates/rooch-rpc-api/src/jsonrpc_types/move_types.rs @@ -10,12 +10,10 @@ use move_core_types::{ u256, }; use move_resource_viewer::{AnnotatedMoveStruct, AnnotatedMoveValue}; -use moveos_types::move_std::ascii::MoveAsciiString; use moveos_types::move_std::string::MoveString; use moveos_types::move_types::parse_module_id; use moveos_types::moveos_std::event::{AnnotatedEvent, Event, EventID}; use moveos_types::moveos_std::type_info::TypeInfo; -use moveos_types::state::MoveStructState; use moveos_types::transaction::MoveAction; use moveos_types::{ access_path::AccessPath, @@ -24,6 +22,7 @@ use moveos_types::{ moveos_std::object::{AnnotatedObject, ObjectID}, transaction::{FunctionCall, ScriptCall}, }; +use moveos_types::{move_std::ascii::MoveAsciiString, state::MoveStructType}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_json::Value; @@ -97,15 +96,15 @@ pub enum SpecificStructView { impl SpecificStructView { pub fn try_from_annotated(move_struct: AnnotatedMoveStruct) -> Option { - if MoveString::type_match(&move_struct.type_) { + if MoveString::struct_tag_match(&move_struct.type_) { MoveString::try_from(move_struct) .ok() .map(SpecificStructView::MoveString) - } else if MoveAsciiString::type_match(&move_struct.type_) { + } else if MoveAsciiString::struct_tag_match(&move_struct.type_) { MoveAsciiString::try_from(move_struct) .ok() .map(SpecificStructView::MoveAsciiString) - } else if ObjectID::type_match(&move_struct.type_) { + } else if ObjectID::struct_tag_match(&move_struct.type_) { ObjectID::try_from(move_struct) .ok() .map(SpecificStructView::ObjectID) diff --git a/crates/rooch-types/src/framework/account_authentication.rs b/crates/rooch-types/src/framework/account_authentication.rs index 2a1106abf9..e6c32d277e 100644 --- a/crates/rooch-types/src/framework/account_authentication.rs +++ b/crates/rooch-types/src/framework/account_authentication.rs @@ -10,7 +10,7 @@ use moveos_types::{ module_binding::{ModuleBinding, MoveFunctionCaller}, move_std::option::MoveOption, moveos_std::tx_context::TxContext, - state::{MoveStructState, MoveStructType}, + state::{MoveState, MoveStructState, MoveStructType}, transaction::FunctionCall, }; use serde::{Deserialize, Serialize}; diff --git a/crates/rooch-types/src/framework/account_coin_store.rs b/crates/rooch-types/src/framework/account_coin_store.rs index 49426b22ab..3d3b88932d 100644 --- a/crates/rooch-types/src/framework/account_coin_store.rs +++ b/crates/rooch-types/src/framework/account_coin_store.rs @@ -9,7 +9,7 @@ use move_core_types::value::MoveValue; use move_core_types::{account_address::AccountAddress, ident_str, identifier::IdentStr}; use moveos_types::move_std::string::MoveString; use moveos_types::moveos_std::object::ObjectID; -use moveos_types::state::{MoveStructState, MoveStructType}; +use moveos_types::state::{MoveState, MoveStructState, MoveStructType}; use moveos_types::{ module_binding::{ModuleBinding, MoveFunctionCaller}, move_std::option::MoveOption, diff --git a/crates/rooch-types/src/framework/address_mapping.rs b/crates/rooch-types/src/framework/address_mapping.rs index ccc2af3e37..8a966f6a23 100644 --- a/crates/rooch-types/src/framework/address_mapping.rs +++ b/crates/rooch-types/src/framework/address_mapping.rs @@ -9,7 +9,7 @@ use moveos_types::{ module_binding::{ModuleBinding, MoveFunctionCaller}, move_std::option::MoveOption, moveos_std::tx_context::TxContext, - state::MoveStructState, + state::MoveState, transaction::FunctionCall, }; diff --git a/crates/rooch-types/src/framework/coin.rs b/crates/rooch-types/src/framework/coin.rs index 37f0644575..c0c06c7156 100644 --- a/crates/rooch-types/src/framework/coin.rs +++ b/crates/rooch-types/src/framework/coin.rs @@ -8,7 +8,7 @@ use move_core_types::u256::U256; use move_core_types::{account_address::AccountAddress, ident_str, identifier::IdentStr}; use moveos_types::move_std::string::MoveString; use moveos_types::moveos_std::object::ObjectID; -use moveos_types::state::{MoveStructState, MoveStructType}; +use moveos_types::state::{MoveState, MoveStructState, MoveStructType}; use moveos_types::{ module_binding::{ModuleBinding, MoveFunctionCaller}, moveos_std::tx_context::TxContext, diff --git a/crates/rooch-types/src/framework/coin_store.rs b/crates/rooch-types/src/framework/coin_store.rs index a0335d3506..c8adf854d9 100644 --- a/crates/rooch-types/src/framework/coin_store.rs +++ b/crates/rooch-types/src/framework/coin_store.rs @@ -6,7 +6,7 @@ use move_core_types::language_storage::StructTag; use move_core_types::u256::U256; use move_core_types::{account_address::AccountAddress, ident_str, identifier::IdentStr}; use moveos_types::move_std::string::MoveString; -use moveos_types::state::{MoveStructState, MoveStructType}; +use moveos_types::state::{MoveState, MoveStructState, MoveStructType}; use serde::{Deserialize, Serialize}; pub const MODULE_NAME: &IdentStr = ident_str!("coin_store"); diff --git a/crates/rooch-types/src/framework/session_key.rs b/crates/rooch-types/src/framework/session_key.rs index 1c6e508f19..c34d9cac0c 100644 --- a/crates/rooch-types/src/framework/session_key.rs +++ b/crates/rooch-types/src/framework/session_key.rs @@ -6,17 +6,14 @@ use crate::authentication_key::AuthenticationKey; use anyhow::Result; use move_core_types::value::MoveValue; use move_core_types::{account_address::AccountAddress, ident_str, identifier::IdentStr}; -use moveos_types::move_std::ascii::MoveAsciiString; use moveos_types::{ module_binding::{ModuleBinding, MoveFunctionCaller}, + move_std::ascii::MoveAsciiString, move_std::option::MoveOption, moveos_std::tx_context::TxContext, - state::MoveState, - transaction::{FunctionCall, MoveAction}, -}; -use moveos_types::{ serde::Readable, - state::{MoveStructState, MoveStructType}, + state::{MoveState, MoveStructState, MoveStructType}, + transaction::{FunctionCall, MoveAction}, }; use serde::{Deserialize, Serialize}; use serde_with::hex::Hex; @@ -52,8 +49,8 @@ impl MoveStructState for SessionScope { fn struct_layout() -> move_core_types::value::MoveStructLayout { move_core_types::value::MoveStructLayout::new(vec![ move_core_types::value::MoveTypeLayout::Address, - ::type_layout(), - ::type_layout(), + MoveAsciiString::type_layout(), + MoveAsciiString::type_layout(), ]) } } @@ -112,9 +109,7 @@ impl MoveStructState for SessionKey { move_core_types::value::MoveTypeLayout::Vector(Box::new( move_core_types::value::MoveTypeLayout::U8, )), - move_core_types::value::MoveTypeLayout::Vector(Box::new( - ::type_layout(), - )), + move_core_types::value::MoveTypeLayout::Vector(Box::new(SessionScope::type_layout())), move_core_types::value::MoveTypeLayout::U64, move_core_types::value::MoveTypeLayout::U64, move_core_types::value::MoveTypeLayout::U64, diff --git a/moveos/moveos-types/Cargo.toml b/moveos/moveos-types/Cargo.toml index 342f4404a9..252c6b2b40 100644 --- a/moveos/moveos-types/Cargo.toml +++ b/moveos/moveos-types/Cargo.toml @@ -32,6 +32,7 @@ proptest = { optional = true, workspace = true } proptest-derive = { optional = true, workspace = true } move-core-types = { workspace = true } +move-vm-types = { workspace = true } move-resource-viewer = { workspace = true } move-bytecode-utils = { workspace = true } move-binary-format = { workspace = true } diff --git a/moveos/moveos-types/src/moveos_std/object_ref.rs b/moveos/moveos-types/src/moveos_std/object_ref.rs index da1d0ad766..032cea5ca2 100644 --- a/moveos/moveos-types/src/moveos_std/object_ref.rs +++ b/moveos/moveos-types/src/moveos_std/object_ref.rs @@ -4,7 +4,7 @@ use crate::{ addresses::MOVEOS_STD_ADDRESS, moveos_std::object::ObjectID, - state::{MoveStructState, MoveStructType}, + state::{MoveState, MoveStructState, MoveStructType}, }; use move_core_types::{ account_address::AccountAddress, ident_str, identifier::IdentStr, language_storage::TypeTag, diff --git a/moveos/moveos-types/src/moveos_std/tx_meta.rs b/moveos/moveos-types/src/moveos_std/tx_meta.rs index 027337cb18..f69362ffac 100644 --- a/moveos/moveos-types/src/moveos_std/tx_meta.rs +++ b/moveos/moveos-types/src/moveos_std/tx_meta.rs @@ -5,7 +5,7 @@ use crate::{ addresses::MOVEOS_STD_ADDRESS, move_std::ascii::MoveAsciiString, move_std::option::MoveOption, - state::{MoveStructState, MoveStructType}, + state::{MoveState, MoveStructState, MoveStructType}, transaction::MoveAction, }; use move_core_types::{account_address::AccountAddress, ident_str, identifier::IdentStr}; diff --git a/moveos/moveos-types/src/state.rs b/moveos/moveos-types/src/state.rs index 19d84d8541..d0c2eba1d0 100644 --- a/moveos/moveos-types/src/state.rs +++ b/moveos/moveos-types/src/state.rs @@ -16,6 +16,7 @@ use move_core_types::{ value::{MoveStructLayout, MoveTypeLayout, MoveValue}, }; use move_resource_viewer::{AnnotatedMoveValue, MoveValueAnnotator}; +use move_vm_types::values::Value; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use smt::UpdateSet; use std::collections::{btree_map, BTreeMap, BTreeSet}; @@ -33,12 +34,16 @@ pub struct State { /// The rust representation of a Move value pub trait MoveType { fn type_tag() -> TypeTag; + + fn type_tag_match(type_tag: &TypeTag) -> bool { + type_tag == &Self::type_tag() + } } /// The rust representation of a Move Struct /// This trait copy from `move_core_types::move_resource::MoveStructType` /// For auto implement `MoveType` to `MoveStructType` -pub trait MoveStructType { +pub trait MoveStructType: MoveType { const ADDRESS: AccountAddress = move_core_types::language_storage::CORE_CODE_ADDRESS; const MODULE_NAME: &'static IdentStr; const STRUCT_NAME: &'static IdentStr; @@ -64,14 +69,51 @@ pub trait MoveStructType { } } - fn type_tag() -> TypeTag { - TypeTag::Struct(Box::new(Self::struct_tag())) + fn struct_tag_match(type_tag: &StructTag) -> bool { + type_tag == &Self::struct_tag() + } +} + +fn type_layout_match(first_layout: &MoveTypeLayout, second_layout: &MoveTypeLayout) -> bool { + match (first_layout, second_layout) { + (MoveTypeLayout::Address, MoveTypeLayout::Address) => true, + (MoveTypeLayout::Signer, MoveTypeLayout::Signer) => true, + (MoveTypeLayout::Bool, MoveTypeLayout::Bool) => true, + (MoveTypeLayout::U8, MoveTypeLayout::U8) => true, + (MoveTypeLayout::U16, MoveTypeLayout::U16) => true, + (MoveTypeLayout::U32, MoveTypeLayout::U32) => true, + (MoveTypeLayout::U64, MoveTypeLayout::U64) => true, + (MoveTypeLayout::U128, MoveTypeLayout::U128) => true, + (MoveTypeLayout::U256, MoveTypeLayout::U256) => true, + ( + MoveTypeLayout::Vector(first_inner_layout), + MoveTypeLayout::Vector(second_inner_layout), + ) => type_layout_match(first_inner_layout, second_inner_layout), + ( + MoveTypeLayout::Struct(first_struct_layout), + MoveTypeLayout::Struct(second_struct_layout), + ) => { + if first_struct_layout.fields().len() != second_struct_layout.fields().len() { + false + } else { + first_struct_layout + .fields() + .iter() + .zip(second_struct_layout.fields().iter()) + .all(|(first_field, second_field)| type_layout_match(first_field, second_field)) + } + } + (_, _) => false, } } /// The rust representation of a Move value state pub trait MoveState: MoveType + DeserializeOwned + Serialize { fn type_layout() -> MoveTypeLayout; + fn type_layout_match(other_type_layout: &MoveTypeLayout) -> bool { + let self_layout = Self::type_layout(); + type_layout_match(&self_layout, other_type_layout) + } fn from_bytes(bytes: &[u8]) -> Result where Self: Sized, @@ -91,6 +133,28 @@ pub trait MoveState: MoveType + DeserializeOwned + Serialize { MoveValue::simple_deserialize(&blob, &Self::type_layout()) .expect("Deserialize the MoveValue from MoveState should success") } + + fn to_runtime_value(&self) -> Value { + let blob = self.to_bytes(); + Value::simple_deserialize(&blob, &Self::type_layout()) + .expect("Deserialize the MoveValue from MoveState should success") + } + + /// Deserialize the MoveState from MoveRuntime Value + fn from_runtime_value(value: Value) -> Result + where + Self: Sized, + { + let blob = value + .simple_serialize(&Self::type_layout()) + .ok_or_else(|| { + anyhow::anyhow!( + "Serialize the MoveState from Value error: {:?}", + Self::type_tag() + ) + })?; + Self::from_bytes(&blob) + } } impl MoveType for u8 { @@ -226,28 +290,8 @@ where /// Move State is a trait that is used to represent the state of a Move Resource in Rust /// It is like the `MoveResource` in move_core_types -pub trait MoveStructState: MoveStructType + DeserializeOwned + Serialize { - fn type_layout() -> MoveTypeLayout { - MoveTypeLayout::Struct(Self::struct_layout()) - } +pub trait MoveStructState: MoveState + MoveStructType + DeserializeOwned + Serialize { fn struct_layout() -> MoveStructLayout; - fn type_match(type_tag: &StructTag) -> bool { - type_tag == &Self::struct_tag() - } - fn from_bytes(bytes: &[u8]) -> Result - where - Self: Sized, - { - bcs::from_bytes(bytes) - .map_err(|e| anyhow::anyhow!("Deserialize the MoveState error: {:?}", e)) - } - fn to_bytes(&self) -> Vec { - bcs::to_bytes(self).expect("Serialize the MoveState should success") - } - fn into_state(self) -> State { - let value = self.to_bytes(); - State::new(value, TypeTag::Struct(Box::new(Self::struct_tag()))) - } } impl From for State @@ -259,6 +303,8 @@ where } } +pub trait MoveRuntimeValue {} + impl State { pub fn new(value: Vec, value_type: TypeTag) -> Self { Self { value, value_type }