Skip to content

Commit

Permalink
[rpc] improve state.list_resource filter (#3615)
Browse files Browse the repository at this point in the history
  • Loading branch information
YouNeedWork authored Aug 11, 2022
1 parent b6aa4f3 commit e2513cb
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 19 deletions.
4 changes: 2 additions & 2 deletions rpc/api/src/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
pub use self::gen_client::Client as StateClient;
use crate::types::{
AccountStateSetView, CodeView, ListCodeView, ListResourceView, ResourceView,
StateWithProofView, StrView,
StateWithProofView, StrView, StructTagView,
};
use crate::FutureResult;
use jsonrpc_derive::rpc;
Expand Down Expand Up @@ -118,7 +118,7 @@ pub struct ListResourceOption {
pub state_root: Option<HashValue>,
pub start_index: usize,
pub max_size: usize,
pub resource_types: Option<Vec<String>>,
pub resource_types: Option<Vec<StructTagView>>,
}

impl Default for ListResourceOption {
Expand Down
2 changes: 1 addition & 1 deletion rpc/client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ impl RpcClient {
state_root: Option<HashValue>,
start_index: usize,
max_size: usize,
resource_types: Option<Vec<String>>,
resource_types: Option<Vec<StructTagView>>,
) -> anyhow::Result<ListResourceView> {
self.call_rpc_blocking(|inner| {
inner.state_client.list_resource(
Expand Down
72 changes: 56 additions & 16 deletions rpc/server/src/module/state_rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ use starcoin_rpc_api::FutureResult;
use starcoin_state_api::{ChainStateAsyncService, StateView};
use starcoin_state_tree::StateNodeStore;
use starcoin_statedb::{ChainStateDB, ChainStateReader};
use starcoin_types::language_storage::ModuleId;
use starcoin_types::language_storage::{ModuleId, TypeTag};
use starcoin_types::{
access_path::AccessPath, account_address::AccountAddress, account_state::AccountState,
};
use starcoin_vm_types::identifier::Identifier;
use starcoin_vm_types::language_storage::StructTag;
use std::collections::{BTreeMap, HashSet};
use std::collections::BTreeMap;
use std::sync::Arc;

pub struct StateRpcImpl<S>
Expand Down Expand Up @@ -267,12 +267,13 @@ where
.state_root
.unwrap_or(state_service.state_root().await?);
let statedb = ChainStateDB::new(db, Some(state_root));
//TODO implement list state by iter, and pagination

let state = statedb.get_account_state_set(&addr)?;
let resource_types_set: Option<HashSet<String>> =
option.resource_types.map(|resource_types_value| {
HashSet::from_iter(resource_types_value.iter().cloned())
});
let resource_types = option.resource_types;
if resource_types.is_some() && resource_types.as_ref().unwrap().len() > 10 {
return Err(anyhow::anyhow!("Query resources is limited by 10"));
}

match state {
None => Ok(ListResourceView::default()),
Some(s) => {
Expand All @@ -282,18 +283,17 @@ where
.unwrap_or_default()
.iter()
.filter(|(k, _)| {
if resource_types_set.is_none() {
if resource_types.is_none() {
return true;
}

let struct_tag = StructTag::decode(k.as_slice()).unwrap();
let resource_type_address_module_name_str = format!(
"{}::{}::{}",
struct_tag.address, struct_tag.module, struct_tag.name
);
resource_types_set
.as_ref()
.unwrap()
.contains(&resource_type_address_module_name_str)
for resource_type in resource_types.as_ref().unwrap() {
if compared_suport_generics(&struct_tag, &resource_type.0) {
return true;
}
}
false
})
.skip(option.start_index)
.take(option.max_size)
Expand Down Expand Up @@ -375,3 +375,43 @@ where
Box::pin(fut.map_err(map_err).boxed())
}
}

fn compared_suport_generics(account_tag: &StructTag, find_tag: &StructTag) -> bool {
if account_tag == find_tag {
return true;
}

if find_tag.address != account_tag.address
|| find_tag.module != account_tag.module
|| find_tag.name != account_tag.name
{
return false;
}

if find_tag.type_params.is_empty()
&& find_tag.address == account_tag.address
&& find_tag.module == account_tag.module
&& find_tag.name == account_tag.name
{
return true;
}

if find_tag.type_params.len() != account_tag.type_params.len() {
return false;
}

let mut res: bool = false;
for (find, account) in std::iter::zip(
find_tag.type_params.clone(),
account_tag.type_params.clone(),
) {
if let (TypeTag::Struct(account), TypeTag::Struct(find)) = (account, find) {
res = compared_suport_generics(&account, &find);
if !res {
return res;
}
}
}

res
}

0 comments on commit e2513cb

Please sign in to comment.