diff --git a/crates/rooch-rpc-server/src/server/rooch_server.rs b/crates/rooch-rpc-server/src/server/rooch_server.rs index 1ea6bb964..b1e5010f7 100644 --- a/crates/rooch-rpc-server/src/server/rooch_server.rs +++ b/crates/rooch-rpc-server/src/server/rooch_server.rs @@ -201,6 +201,7 @@ impl RoochAPIServer for RoochServer { access_path: AccessPathView, state_option: Option, ) -> RpcResult>> { + access_path.0.validate_max_object_ids()?; let state_option = state_option.unwrap_or_default(); let show_display = state_option.show_display && (access_path.0.is_object() || access_path.0.is_resource()); @@ -257,6 +258,7 @@ impl RoochAPIServer for RoochServer { limit: Option>, state_option: Option, ) -> RpcResult { + access_path.0.validate_max_object_ids()?; let state_option = state_option.unwrap_or_default(); let show_display = state_option.show_display && (access_path.0.is_object() || access_path.0.is_resource()); diff --git a/crates/rooch-rpc-server/src/service/rpc_service.rs b/crates/rooch-rpc-server/src/service/rpc_service.rs index 6824a4a24..c3268e0ba 100644 --- a/crates/rooch-rpc-server/src/service/rpc_service.rs +++ b/crates/rooch-rpc-server/src/service/rpc_service.rs @@ -12,7 +12,7 @@ use moveos_types::module_binding::MoveFunctionCaller; use moveos_types::move_types::type_tag_match; use moveos_types::moveos_std::display::{get_object_display_id, RawDisplay}; use moveos_types::moveos_std::event::{AnnotatedEvent, Event, EventID}; -use moveos_types::moveos_std::object::ObjectID; +use moveos_types::moveos_std::object::{ObjectID, MAX_OBJECT_IDS_PER_QUERY}; use moveos_types::state::{AnnotatedState, FieldKey, ObjectState, StateChangeSet}; use moveos_types::state_resolver::{AnnotatedStateKV, StateKV}; use moveos_types::transaction::{FunctionCall, TransactionExecutionInfo}; @@ -358,16 +358,14 @@ impl RpcService { show_display: bool, state_type: ObjectStateType, ) -> Result> { - const MAX_OBJECT_IDS: usize = 100; - let indexer_ids = match filter { // Compatible with object_ids query after split object_states // Do not query the indexer, directly return the states query results. ObjectStateFilter::ObjectId(object_ids) => { - if object_ids.len() > MAX_OBJECT_IDS { + if object_ids.len() > MAX_OBJECT_IDS_PER_QUERY { return Err(anyhow::anyhow!( "Too many object IDs requested. Maximum allowed: {}", - MAX_OBJECT_IDS + MAX_OBJECT_IDS_PER_QUERY )); } object_ids @@ -588,18 +586,29 @@ impl RpcService { match repair_type { RepairIndexerType::ObjectState => match repair_params { RepairIndexerParams::ObjectId(object_ids) => { - self.repair_indexer_object_states( - object_ids.clone(), + if object_ids.len() > MAX_OBJECT_IDS_PER_QUERY { + return Err(anyhow::anyhow!( + "Too many object IDs requested. Maximum allowed: {}", + MAX_OBJECT_IDS_PER_QUERY + )); + } + let states = self + .get_states(AccessPath::objects(object_ids.clone()), None) + .await?; + for state_type in [ ObjectStateType::ObjectState, - ) - .await?; - self.repair_indexer_object_states( - object_ids.clone(), ObjectStateType::UTXO, - ) - .await?; - self.repair_indexer_object_states(object_ids, ObjectStateType::Inscription) - .await + ObjectStateType::Inscription, + ] { + self.repair_indexer_object_states( + states.clone(), + &object_ids, + state_type, + ) + .await?; + } + + Ok(()) } _ => Err(format_err!( "Invalid params when repair indexer for ObjectState" @@ -617,14 +626,11 @@ impl RpcService { pub async fn repair_indexer_object_states( &self, - object_ids: Vec, + states: Vec>, + object_ids: &[ObjectID], state_type: ObjectStateType, ) -> Result<()> { { - let states = self - .get_states(AccessPath::objects(object_ids.clone()), None) - .await?; - let mut remove_object_ids = vec![]; let mut object_states_mapping = HashMap::new(); for (idx, state_opt) in states.into_iter().enumerate() { diff --git a/moveos/moveos-types/src/access_path.rs b/moveos/moveos-types/src/access_path.rs index 76d0c37c1..9bbeaa1a7 100644 --- a/moveos/moveos-types/src/access_path.rs +++ b/moveos/moveos-types/src/access_path.rs @@ -6,7 +6,7 @@ use crate::moveos_std::module_store::Package; use crate::state::FieldKey; use crate::{ move_types::{random_identity, random_struct_tag}, - moveos_std::object::ObjectID, + moveos_std::object::{ObjectID, MAX_OBJECT_IDS_PER_QUERY}, }; use anyhow::{ensure, Result}; use move_core_types::language_storage::ModuleId; @@ -291,6 +291,18 @@ impl AccessPath { }) } + pub fn validate_max_object_ids(&self) -> Result<()> { + if let Path::Object { object_ids } = &self.0 { + if object_ids.len() > MAX_OBJECT_IDS_PER_QUERY { + return Err(anyhow::anyhow!( + "Too many object IDs requested. Maximum allowed: {}", + MAX_OBJECT_IDS_PER_QUERY + )); + } + } + Ok(()) + } + /// Convert AccessPath to StateQuery, return the ObjectID and field keys pub fn into_state_query(self) -> StateQuery { match self.0 { diff --git a/moveos/moveos-types/src/moveos_std/object.rs b/moveos/moveos-types/src/moveos_std/object.rs index f80cb8f31..c0e82ee6b 100644 --- a/moveos/moveos-types/src/moveos_std/object.rs +++ b/moveos/moveos-types/src/moveos_std/object.rs @@ -52,6 +52,8 @@ pub const SYSTEM_OWNER_ADDRESS: AccountAddress = AccountAddress::ZERO; pub const SHARED_OBJECT_FLAG_MASK: u8 = 1; pub const FROZEN_OBJECT_FLAG_MASK: u8 = 1 << 1; +pub const MAX_OBJECT_IDS_PER_QUERY: usize = 100; + // New table's state_root should be the place holder hash. pub static GENESIS_STATE_ROOT: Lazy = Lazy::new(|| *SPARSE_MERKLE_PLACEHOLDER_HASH);