Skip to content

Commit

Permalink
[RPC] Limit the number of struct elements in a Move struct when query…
Browse files Browse the repository at this point in the history
…ing (#2924)

forbidden query large vector of struct
  • Loading branch information
pause125 authored Nov 20, 2024
1 parent 48e7da6 commit 392e883
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 8 deletions.
20 changes: 20 additions & 0 deletions crates/rooch-rpc-api/src/jsonrpc_types/move_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,26 @@ pub enum AnnotatedMoveValueView {
U256(StrView<u256::U256>),
}

impl AnnotatedMoveValueView {
/// Calculate the total number of Move structs recursively
pub fn size_of_struct_recursively(origin: &AnnotatedMoveValue) -> usize {
match origin {
AnnotatedMoveValue::Vector(_, data) => match data.first() {
Some(first) => Self::size_of_struct_recursively(first) * data.len(),
None => 0,
},
AnnotatedMoveValue::Struct(data) => {
let mut size = 1;
for (_, v) in &data.value {
size += Self::size_of_struct_recursively(v);
}
size
}
_ => 0,
}
}
}

impl From<AnnotatedMoveValue> for AnnotatedMoveValueView {
fn from(origin: AnnotatedMoveValue) -> Self {
match origin {
Expand Down
31 changes: 27 additions & 4 deletions crates/rooch-rpc-api/src/jsonrpc_types/state_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
// SPDX-License-Identifier: Apache-2.0

use super::{
AnnotatedMoveStructView, BytesView, H256View, HumanReadableDisplay, ObjectIDVecView,
ObjectIDView, QueryOptions, RoochAddressView, StrView, StructTagView, TypeTagView,
UnitedAddressView,
AnnotatedMoveStructView, AnnotatedMoveValueView, BytesView, H256View, HumanReadableDisplay,
ObjectIDVecView, ObjectIDView, QueryOptions, RoochAddressView, StrView, StructTagView,
TypeTagView, UnitedAddressView,
};
use anyhow::Result;
use move_core_types::effects::Op;
Expand Down Expand Up @@ -328,6 +328,29 @@ impl IndexerObjectStateView {
}
}

pub fn try_new_from_annotated_state(
state: AnnotatedState,
indexer_id: IndexerStateID,
) -> Result<IndexerObjectStateView> {
let (metadata, value, decoded_value) = state.into_inner();
let mut size = 0;
decoded_value.value.iter().for_each(|(_k, v)| {
size += AnnotatedMoveValueView::size_of_struct_recursively(v);
});
// make the size limit configurable
if size > 200 {
anyhow::bail!("The size of the object is too large to decode and display");
}

Ok(IndexerObjectStateView {
metadata: metadata.into(),
value: value.into(),
decoded_value: Some(AnnotatedMoveStructView::from(decoded_value)),
indexer_id: indexer_id.into(),
display_fields: None,
})
}

pub fn with_owner_bitcoin_address(mut self, owner_bitcoin_address: Option<String>) -> Self {
self.metadata.owner_bitcoin_address = owner_bitcoin_address;
self
Expand Down Expand Up @@ -504,7 +527,7 @@ fn parse_changed_objects(
let mut deleted_objs = vec![];
for obj_change in changes {
let metadata = obj_change.metadata.clone();
debug_assert!(obj_change.value.is_some() || !obj_change.fields.is_empty());
// There may have 3 type of changes: metadata, value, fields
match obj_change.value {
Some(OpView::New(_)) => new_objs.push(metadata),
Some(OpView::Modify(_)) => modified_objs.push(metadata),
Expand Down
8 changes: 4 additions & 4 deletions crates/rooch-rpc-server/src/service/rpc_service.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) RoochNetwork
// SPDX-License-Identifier: Apache-2.0

use anyhow::{format_err, Ok, Result};
use anyhow::{format_err, Result};
use bitcoincore_rpc::bitcoin::Txid;
use move_core_types::account_address::AccountAddress;
use move_core_types::language_storage::{ModuleId, StructTag};
Expand Down Expand Up @@ -404,12 +404,12 @@ impl RpcService {
} else {
BTreeMap::new()
};
let mut object_states: Vec<IndexerObjectStateView> = annotated_states
let mut object_states = annotated_states
.into_iter()
.zip(indexer_ids)
.filter_map(|(state_opt, (object_id, indexer_state_id))| {
match state_opt {
Some(state) => Some(IndexerObjectStateView::new_from_annotated_state(
Some(state) => Some(IndexerObjectStateView::try_new_from_annotated_state(
state,
indexer_state_id,
)),
Expand All @@ -423,7 +423,7 @@ impl RpcService {
}
}
})
.collect();
.collect::<Result<Vec<_>>>()?;
if !displays.is_empty() {
object_states.iter_mut().for_each(|object_state| {
object_state.display_fields =
Expand Down

0 comments on commit 392e883

Please sign in to comment.