Skip to content

Commit

Permalink
[Break RPC]optimize memory usage of query_object_states (#2884)
Browse files Browse the repository at this point in the history
* optimize memory usage of query_object_states

* fix

* fix test cases

* fix jemallocator

* optimize memory usage of query_object_states

* fix

* fix test cases

* fix jemallocator

* fix sdk test

---------

Co-authored-by: sven Tan <[email protected]>
  • Loading branch information
pause125 and wow-sven authored Nov 15, 2024
1 parent 20c9407 commit 7b74fde
Show file tree
Hide file tree
Showing 11 changed files with 244 additions and 19 deletions.
44 changes: 44 additions & 0 deletions crates/rooch-open-rpc-spec/schemas/openrpc.json
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,47 @@
}
}
},
"AnnotatedMoveStructVectorView": {
"type": "object",
"required": [
"abilities",
"field",
"type",
"value"
],
"properties": {
"abilities": {
"description": "alilities of each element",
"type": "integer",
"format": "uint8",
"minimum": 0.0
},
"field": {
"description": "field of each element",
"type": "array",
"items": {
"$ref": "#/components/schemas/move_core_types::identifier::Identifier"
}
},
"type": {
"description": "type of each element",
"allOf": [
{
"$ref": "#/components/schemas/move_core_types::language_storage::StructTag"
}
]
},
"value": {
"type": "array",
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/AnnotatedMoveValueView"
}
}
}
}
},
"AnnotatedMoveStructView": {
"type": "object",
"required": [
Expand Down Expand Up @@ -915,6 +956,9 @@
"$ref": "#/components/schemas/AnnotatedMoveValueView"
}
},
{
"$ref": "#/components/schemas/AnnotatedMoveStructVectorView"
},
{
"$ref": "#/components/schemas/alloc::vec::Vec<u8>"
},
Expand Down
65 changes: 62 additions & 3 deletions crates/rooch-rpc-api/src/jsonrpc_types/move_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,61 @@ impl From<AnnotatedMoveStruct> for AnnotatedMoveStructView {
}
}

#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Eq, PartialEq, PartialOrd, Ord)]
pub struct AnnotatedMoveStructVectorView {
/// alilities of each element
pub abilities: u8,
#[serde(rename = "type")]
/// type of each element
pub type_: StructTagView,
/// field of each element
pub field: Vec<IdentifierView>,
// values of the whole vector
pub value: Vec<Vec<AnnotatedMoveValueView>>,
}

impl AnnotatedMoveStructVectorView {
fn try_from(origin: Vec<AnnotatedMoveValue>) -> Result<Self, AnnotatedMoveValueView> {
if origin.is_empty() {
Err(AnnotatedMoveValueView::Vector(
origin.into_iter().map(Into::into).collect(),
))
} else {
let first = origin.first().unwrap();
if let AnnotatedMoveValue::Struct(ele) = first {
let field = ele
.value
.iter()
.map(|x| IdentifierView::from(x.0.clone()))
.collect();
let abilities = ele.abilities.into_u8();
let type_ = StrView(ele.type_.clone());
let value: Vec<Vec<AnnotatedMoveValueView>> = origin
.into_iter()
.map(|v| {
if let AnnotatedMoveValue::Struct(s) = v {
s.value.into_iter().map(|(_, v)| v.into()).collect()
} else {
unreachable!("AnnotatedMoveStructVectorView")
}
})
.collect();

Ok(Self {
abilities,
type_,
field,
value,
})
} else {
Err(AnnotatedMoveValueView::Vector(
origin.into_iter().map(Into::into).collect(),
))
}
}
}
}

/// Some specific struct that we want to display in a special way for better readability
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Eq, PartialEq, PartialOrd, Ord)]
#[serde(untagged)]
Expand All @@ -161,7 +216,7 @@ pub enum SpecificStructView {
}

impl SpecificStructView {
pub fn try_from_annotated(move_struct: AnnotatedMoveStruct) -> Option<Self> {
pub fn try_from_annotated(move_struct: &AnnotatedMoveStruct) -> Option<Self> {
if MoveString::struct_tag_match(&move_struct.type_) {
MoveString::try_from(move_struct)
.ok()
Expand Down Expand Up @@ -192,6 +247,7 @@ pub enum AnnotatedMoveValueView {
Bool(bool),
Address(AccountAddressView),
Vector(Vec<AnnotatedMoveValueView>),
StructVector(Box<AnnotatedMoveStructVectorView>),
Bytes(BytesView),
Struct(AnnotatedMoveStructView),
SpecificStruct(SpecificStructView),
Expand All @@ -209,11 +265,14 @@ impl From<AnnotatedMoveValue> for AnnotatedMoveValueView {
AnnotatedMoveValue::Bool(b) => AnnotatedMoveValueView::Bool(b),
AnnotatedMoveValue::Address(data) => AnnotatedMoveValueView::Address(StrView(data)),
AnnotatedMoveValue::Vector(_type_tag, data) => {
AnnotatedMoveValueView::Vector(data.into_iter().map(Into::into).collect())
match AnnotatedMoveStructVectorView::try_from(data) {
Ok(v) => AnnotatedMoveValueView::StructVector(Box::new(v)),
Err(v) => v,
}
}
AnnotatedMoveValue::Bytes(data) => AnnotatedMoveValueView::Bytes(StrView(data)),
AnnotatedMoveValue::Struct(data) => {
match SpecificStructView::try_from_annotated(data.clone()) {
match SpecificStructView::try_from_annotated(&data) {
Some(struct_view) => AnnotatedMoveValueView::SpecificStruct(struct_view),
None => AnnotatedMoveValueView::Struct(data.into()),
}
Expand Down
4 changes: 2 additions & 2 deletions crates/rooch-rpc-server/src/service/rpc_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ impl RpcService {
} else {
BTreeMap::new()
};
let mut object_states = annotated_states
let mut object_states: Vec<IndexerObjectStateView> = annotated_states
.into_iter()
.zip(indexer_ids)
.filter_map(|(state_opt, (object_id, indexer_state_id))| {
Expand All @@ -423,7 +423,7 @@ impl RpcService {
}
}
})
.collect::<Vec<_>>();
.collect();
if !displays.is_empty() {
object_states.iter_mut().for_each(|object_state| {
object_state.display_fields =
Expand Down
26 changes: 19 additions & 7 deletions crates/testsuite/features/bitseed.feature
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ Feature: Rooch CLI bitseed tests
# Check mint generator validity
Then cmd: "move view --function 0x4::ord::view_validity --args string:{{$.bitseed[-1].inscriptions[0].Id}} "
Then assert: "{{$.move[-1].vm_status}} == Executed"
Then assert: "{{$.move[-1].return_values[0].decoded_value.value.vec[0].value.is_valid}} == true"
# For `.vec.value[0][1]`, the first index `0` means the first element of vec;
# the second index `1` means the second field of `0x4::ord::MetaprotocolValidity`, that is `is_valid`.
Then assert: "{{$.move[-1].return_values[0].decoded_value.value.vec.value[0][1]}} == true"

# deploy
Then cmd: "bitseed deploy --fee-rate 6000 --generator {{$.bitseed[-1].inscriptions[0].Id}} --tick bits --amount 210000000000 --deploy-args '{"height":{"type":"range","data":{"min":1,"max":1000}}}'"
Expand All @@ -48,7 +50,9 @@ Feature: Rooch CLI bitseed tests
# Check deploy validity
Then cmd: "move view --function 0x4::ord::view_validity --args string:{{$.bitseed[-1].inscriptions[0].Id}} "
Then assert: "{{$.move[-1].vm_status}} == Executed"
Then assert: "{{$.move[-1].return_values[0].decoded_value.value.vec[0].value.is_valid}} == true"
# For `.vec.value[0][1]`, the first index `0` means the first element of vec;
# the second index `1` means the second field of `0x4::ord::MetaprotocolValidity`, that is `is_valid`.
Then assert: "{{$.move[-1].return_values[0].decoded_value.value.vec.value[0][1]}} == true"

# mint 1
Then cmd: "bitseed mint --fee-rate 6000 --deploy-inscription-id {{$.bitseed[-1].inscriptions[0].Id}} --user-input test"
Expand All @@ -72,11 +76,15 @@ Feature: Rooch CLI bitseed tests
# Check mint bits validity
Then cmd: "move view --function 0x4::ord::view_validity --args string:{{$.bitseed[-1].inscriptions[0].Id}} "
Then assert: "{{$.move[-1].vm_status}} == Executed"
Then assert: "{{$.move[-1].return_values[0].decoded_value.value.vec[0].value.is_valid}} == true"
# For `.vec.value[0][1]`, the first index `0` means the first element of vec;
# the second index `1` means the second field of `0x4::ord::MetaprotocolValidity`, that is `is_valid`.
Then assert: "{{$.move[-1].return_values[0].decoded_value.value.vec.value[0][1]}} == true"

Then cmd: "move view --function 0x4::ord::view_validity --args string:{{$.bitseed[-2].inscriptions[0].Id}} "
Then assert: "{{$.move[-1].vm_status}} == Executed"
Then assert: "{{$.move[-1].return_values[0].decoded_value.value.vec[0].value.is_valid}} == true"
# For `.vec.value[0][1]`, the first index `0` means the first element of vec;
# the second index `1` means the second field of `0x4::ord::MetaprotocolValidity`, that is `is_valid`.
Then assert: "{{$.move[-1].return_values[0].decoded_value.value.vec.value[0][1]}} == true"

Then cmd: "bitseed merge --fee-rate 6000 --sft-inscription-ids {{$.bitseed[-1].inscriptions[0].Id}} --sft-inscription-ids {{$.bitseed[-2].inscriptions[0].Id}}"
Then assert: "'{{$.bitseed[-1]}}' not_contains error"
Expand All @@ -90,8 +98,10 @@ Feature: Rooch CLI bitseed tests

Then cmd: "move view --function 0x4::ord::view_validity --args string:{{$.bitseed[-1].inscriptions[0].Id}} "
Then assert: "{{$.move[-1].vm_status}} == Executed"
Then assert: "{{$.move[-1].return_values[0].decoded_value.value.vec[0].value.is_valid}} == true"

# For `.vec.value[0][1]`, the first index `0` means the first element of vec;
# the second index `1` means the second field of `0x4::ord::MetaprotocolValidity`, that is `is_valid`.
Then assert: "{{$.move[-1].return_values[0].decoded_value.value.vec.value[0][1]}} == true"

# release servers
Then stop the server
Then stop the bitcoind server
Expand Down Expand Up @@ -130,7 +140,9 @@ Feature: Rooch CLI bitseed tests
# Check deploy validity
Then cmd: "move view --function 0x4::ord::view_validity --args string:{{$.bitseed[-1].inscriptions[0].Id}} "
Then assert: "{{$.move[-1].vm_status}} == Executed"
Then assert: "{{$.move[-1].return_values[0].decoded_value.value.vec[0].value.is_valid}} == true"
# For `.vec.value[0][1]`, the first index `0` means the first element of vec;
# the second index `1` means the second field of `0x4::ord::MetaprotocolValidity`, that is `is_valid`.
Then assert: "{{$.move[-1].return_values[0].decoded_value.value.vec.value[0][1]}} == true"

# mint on rooch
Then cmd: "move run --function 0xa::mint_get_factory::mint --args string:bitseed --args string:test --json"
Expand Down
4 changes: 3 additions & 1 deletion crates/testsuite/features/ord.feature
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ Feature: Rooch Bitcoin ord tests
# Check inscription burned
Then cmd: "move view --function 0x4::ord::view_inscription_charm --args string:{{$.wallet[-3][0].inscription}} "
Then assert: "{{$.move[-1].vm_status}} == Executed"
Then assert: "{{$.move[-1].return_values[0].decoded_value.value.vec[0].value.burned}} == true"
# For `.vec.value[0][1]`, the first index `0` means the first element of vec;
# the second index `12` means the 13th field of `0x4::ord::InscriptionCharm`, that is `burned`.
Then assert: "{{$.move[-1].return_values[0].decoded_value.value.vec.value[0][12]}} == true"

# release servers
Then stop the server
Expand Down
20 changes: 20 additions & 0 deletions moveos/moveos-types/src/move_std/ascii.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,26 @@ impl TryFrom<AnnotatedMoveStruct> for MoveAsciiString {
}
}

impl TryFrom<&AnnotatedMoveStruct> for MoveAsciiString {
type Error = anyhow::Error;

fn try_from(value: &AnnotatedMoveStruct) -> Result<Self, Self::Error> {
let annotated_move_struct = value;
let (field_name, field_value) = annotated_move_struct
.value
.first()
.ok_or_else(|| anyhow::anyhow!("Invalid MoveAsciiString"))?;
debug_assert!(field_name.as_str() == "bytes");
let bytes = match field_value {
AnnotatedMoveValue::Bytes(bytes) => bytes,
_ => return Err(anyhow::anyhow!("Invalid MoveAsciiString")),
};
Ok(MoveAsciiString {
bytes: bytes.clone(),
})
}
}

impl TryFrom<MoveAsciiString> for Identifier {
type Error = anyhow::Error;

Expand Down
20 changes: 20 additions & 0 deletions moveos/moveos-types/src/move_std/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,26 @@ impl TryFrom<AnnotatedMoveStruct> for MoveString {
}
}

impl TryFrom<&AnnotatedMoveStruct> for MoveString {
type Error = anyhow::Error;

fn try_from(value: &AnnotatedMoveStruct) -> Result<Self, Self::Error> {
let annotated_move_struct = value;
let (field_name, field_value) = annotated_move_struct
.value
.first()
.ok_or_else(|| anyhow::anyhow!("Invalid MoveString"))?;
debug_assert!(field_name.as_str() == "bytes");
let bytes = match field_value {
AnnotatedMoveValue::Bytes(bytes) => bytes,
_ => return Err(anyhow::anyhow!("Invalid MoveString")),
};
Ok(MoveString {
bytes: bytes.clone(),
})
}
}

impl TryFrom<MoveString> for Identifier {
type Error = anyhow::Error;

Expand Down
21 changes: 21 additions & 0 deletions moveos/moveos-types/src/moveos_std/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,19 @@ impl TryFrom<AnnotatedMoveValue> for ObjectID {
}
}

impl TryFrom<&AnnotatedMoveValue> for ObjectID {
type Error = anyhow::Error;

fn try_from(value: &AnnotatedMoveValue) -> Result<Self, Self::Error> {
match value {
AnnotatedMoveValue::Struct(annotated_move_struct) => {
ObjectID::try_from(annotated_move_struct)
}
_ => Err(anyhow::anyhow!("Invalid ObjectID")),
}
}
}

impl TryFrom<AnnotatedMoveStruct> for ObjectID {
type Error = anyhow::Error;

Expand All @@ -303,6 +316,14 @@ impl TryFrom<AnnotatedMoveStruct> for ObjectID {
}
}

impl TryFrom<&AnnotatedMoveStruct> for ObjectID {
type Error = anyhow::Error;

fn try_from(value: &AnnotatedMoveStruct) -> Result<Self, Self::Error> {
ObjectID::try_from_annotated_move_struct_ref(value)
}
}

impl From<AccountAddress> for ObjectID {
fn from(address: AccountAddress) -> Self {
ObjectID(vec![address])
Expand Down
17 changes: 12 additions & 5 deletions sdk/typescript/rooch-sdk/src/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ export class RoochClient {
if (result.vm_status === 'Executed' && result.return_values) {
const value = (result.return_values?.[0]?.decoded_value as AnnotatedMoveStructView).value

const address = (((value as any).vec[0] as AnnotatedMoveStructView).value as any).bytes
const address = (((value as any).vec as AnnotatedMoveStructView).value[0] as Array<string>)[0]

return new BitcoinAddress(address, input.network)
}
Expand Down Expand Up @@ -411,7 +411,14 @@ export class RoochClient {
hasNextPage: false,
}
}

const sss = (
(
(states?.[0]?.decoded_value as AnnotatedMoveStructView).value[
'value'
] as AnnotatedMoveStructView
).value['keys'] as AnnotatedMoveStructView
).value['handle'] as AnnotatedMoveStructView
console.log(sss)
// Maybe we should define the type?
const tableId = (
(
Expand Down Expand Up @@ -439,8 +446,8 @@ export class RoochClient {
const result = new Array<string>()

for (const scope of data) {
const value = scope.value
result.push(`${value.module_address}::${value.module_name}::${value.function_name}`)
const [pkg, mod, fn] = [scope[0], scope[1], scope[2]]
result.push(`${pkg}::${mod}::${fn}`)
}

return result
Expand All @@ -459,7 +466,7 @@ export class RoochClient {
appName: val.app_name,
appUrl: val.app_url,
authenticationKey: val.authentication_key,
scopes: parseScopes(val.scopes),
scopes: parseScopes(val.scopes.value),
createTime: parseInt(val.create_time),
lastActiveTime: parseInt(val.last_active_time),
maxInactiveInterval: parseInt(val.max_inactive_interval),
Expand Down
Loading

0 comments on commit 7b74fde

Please sign in to comment.