Skip to content

Commit

Permalink
[object] Parse the account dynamic field
Browse files Browse the repository at this point in the history
  • Loading branch information
jolestar committed Jul 6, 2024
1 parent 86db9c9 commit 25db745
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 8 deletions.
1 change: 0 additions & 1 deletion moveos/moveos-types/src/access_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,6 @@ impl<'de> Deserialize<'de> for AccessPath {
#[cfg(test)]
mod tests {
use super::*;
use crate::move_std::string::MoveString;

fn test_path_roundtrip(path: &str) {
let path = path.parse::<Path>().unwrap();
Expand Down
2 changes: 1 addition & 1 deletion moveos/moveos-types/src/moveos_std/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use std::str::FromStr;

pub use dynamic_field::{
construct_dynamic_field_struct_tag, is_dynamic_field_type, is_field_struct_tag, DynamicField,
DYNAMIC_FIELD_STRUCT_NAME,
RawField, DYNAMIC_FIELD_STRUCT_NAME,
};

mod dynamic_field;
Expand Down
121 changes: 120 additions & 1 deletion moveos/moveos-types/src/moveos_std/object/dynamic_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@

use crate::{
addresses::MOVEOS_STD_ADDRESS,
state::{MoveState, MoveStructState, MoveStructType},
move_std::string::MoveString,
state::{MoveState, MoveStructState, MoveStructType, MoveType},
};
use anyhow::{anyhow, bail, Result};
use move_core_types::{
ident_str,
identifier::IdentStr,
Expand All @@ -30,6 +32,85 @@ impl<N, V> DynamicField<N, V> {
}
}

#[derive(Debug, Clone)]
pub struct RawField {
pub name: Vec<u8>,
pub name_type: TypeTag,
pub value: Vec<u8>,
pub value_type: TypeTag,
}

impl RawField {
pub fn new(name: Vec<u8>, name_type: TypeTag, value: Vec<u8>, value_type: TypeTag) -> Self {
Self {
name,
name_type,
value,
value_type,
}
}

pub fn from_dynamic_field<N, V>(field: &DynamicField<N, V>) -> Self
where
N: MoveState,
V: MoveState,
{
Self {
name: field.name.to_bytes(),
name_type: N::type_tag(),
value: field.value.to_bytes(),
value_type: V::type_tag(),
}
}

//This function is from bcs module,
//find a better way to parse the vec.
fn parse_length(bytes: &[u8]) -> Result<(usize, usize)> {
let mut value: u64 = 0;
let mut iter = bytes.iter();
let mut used_bytes: usize = 0;
for shift in (0..32).step_by(7) {
let byte = *iter
.next()
.ok_or_else(|| anyhow!("Invalid bytes, NonCanonicalUleb128Encoding"))?;
used_bytes += 1;
let digit = byte & 0x7f;
value |= u64::from(digit) << shift;
// If the highest bit of `byte` is 0, return the final value.
if digit == byte {
if shift > 0 && digit == 0 {
// We only accept canonical ULEB128 encodings, therefore the
// heaviest (and last) base-128 digit must be non-zero.
bail!("Invalid bytes, NonCanonicalUleb128Encoding");
}
// Decoded integer must not overflow.
return Ok((
used_bytes,
u32::try_from(value).map_err(|_| {
anyhow!("Invalid bytes, IntegerOverflowDuringUleb128Decoding")
})? as usize,
));
}
}
// Decoded integer must not overflow.
bail!("Invalid bytes, IntegerOverflowDuringUleb128Decoding")
}

/// Parse bcs serialized `DynamicField<MoveString,T>` bytes to `RawField`
pub fn parse_resource_field(bytes: &[u8], value_type: TypeTag) -> anyhow::Result<Self> {
let (used_bytes, name_length) = Self::parse_length(bytes)?;
let name_bytes_length = used_bytes + name_length;
let name = &bytes[..name_bytes_length];
let value = &bytes[name_bytes_length..];
Ok(Self {
name: name.to_vec(),
name_type: MoveString::type_tag(),
value: value.to_vec(),
value_type,
})
}
}

impl<N, V> MoveStructType for DynamicField<N, V>
where
N: MoveState,
Expand Down Expand Up @@ -94,3 +175,41 @@ pub fn construct_dynamic_field_struct_tag(name_tag: TypeTag, value_tag: TypeTag)
type_params: vec![name_tag, value_tag],
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::{move_std::string::MoveString, state::MoveType};
use move_core_types::account_address::AccountAddress;

#[derive(Eq, PartialEq, Debug, Clone, Deserialize, Serialize)]
struct TestStruct {
count: u64,
}

impl MoveStructType for TestStruct {
const ADDRESS: AccountAddress = MOVEOS_STD_ADDRESS;
const MODULE_NAME: &'static IdentStr = ident_str!("object");
const STRUCT_NAME: &'static IdentStr = ident_str!("TestStruct");
}

impl MoveStructState for TestStruct {
fn struct_layout() -> MoveStructLayout {
MoveStructLayout::new(vec![MoveTypeLayout::U64])
}
}

#[test]
fn test_dynamic_field() {
let field = DynamicField::new(
MoveString::from(TestStruct::struct_tag().to_canonical_string()),
TestStruct { count: 10 },
);
let raw_field_bytes = bcs::to_bytes(&field).unwrap();
let raw_field = RawField::from_dynamic_field(&field);
let parsed_raw_field =
RawField::parse_resource_field(&raw_field_bytes, TestStruct::type_tag()).unwrap();
assert_eq!(raw_field.name, parsed_raw_field.name);
assert_eq!(raw_field.value, parsed_raw_field.value);
}
}
12 changes: 9 additions & 3 deletions moveos/moveos-types/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,9 +576,15 @@ where
}
}

impl MoveType for String {
fn type_tag() -> TypeTag {
MoveString::type_tag()
impl MoveStructType for String {
const ADDRESS: AccountAddress = MoveString::ADDRESS;
const MODULE_NAME: &'static IdentStr = MoveString::MODULE_NAME;
const STRUCT_NAME: &'static IdentStr = MoveString::STRUCT_NAME;
}

impl MoveStructState for String {
fn struct_layout() -> MoveStructLayout {
MoveString::struct_layout()
}
}

Expand Down
5 changes: 3 additions & 2 deletions moveos/moveos-types/src/state_resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::move_std::string::MoveString;
use crate::moveos_std::account::Account;
use crate::moveos_std::module_store::Package;
use crate::moveos_std::move_module::MoveModuleDynamicField;
use crate::moveos_std::object::{ObjectEntity, ObjectID};
use crate::moveos_std::object::{ObjectEntity, ObjectID, RawField};
use crate::state::{FieldKey, MoveType, ObjectState};
use crate::{
access_path::AccessPath, h256::H256, moveos_std::object::AnnotatedObject, state::AnnotatedState,
Expand Down Expand Up @@ -161,7 +161,8 @@ where
resource_tag,
s.value_type()
);
Ok(s.value)
let field = RawField::parse_resource_field(&s.value, resource_tag.clone().into())?;
Ok(field.value)
})
.transpose();

Expand Down

0 comments on commit 25db745

Please sign in to comment.