iota_core/
verify_indexes.rs1use std::{collections::BTreeMap, sync::Arc};
6
7use anyhow::{Result, anyhow, bail};
8use iota_sdk_types::Owner;
9use iota_types::base_types::ObjectInfo;
10use tracing::info;
11use typed_store::traits::Map;
12
13use crate::{
14 global_state_hasher::GlobalStateHashStore,
15 jsonrpc_index::{CoinInfo, IndexStore},
16};
17
18pub fn verify_indexes(store: &dyn GlobalStateHashStore, indexes: Arc<IndexStore>) -> Result<()> {
22 info!("Begin running index verification checks");
23
24 let mut owner_index = BTreeMap::new();
25 let mut coin_index = BTreeMap::new();
26
27 tracing::info!("Reading live objects set");
28 for live_object in store.iter_live_object_set() {
29 let object = &live_object.object;
30 let Owner::Address(owner) = object.owner else {
31 continue;
32 };
33
34 let owner_index_key = (owner, object.id());
36 let object_info = ObjectInfo::new(&object.object_ref(), object);
37
38 owner_index.insert(owner_index_key, object_info);
39
40 if let Some(type_tag) = object.opt_coin_type() {
42 let info =
43 CoinInfo::from_object(object).expect("already checked that this is a coin type");
44 let key = (owner, type_tag.to_string(), object.id());
45
46 coin_index.insert(key, info);
47 }
48 }
49
50 tracing::info!("Live objects set is prepared, about to verify indexes");
51
52 for item in indexes.tables().owner_index().safe_iter() {
54 let (key, info) = item?;
55 let calculated_info = owner_index.remove(&key).ok_or_else(|| {
56 anyhow!(
57 "owner_index: found extra, unexpected entry {:?}",
58 (&key, &info)
59 )
60 })?;
61
62 if calculated_info != info {
63 bail!(
64 "owner_index: entry {key:?} is different: expected {calculated_info:?} found {info:?}"
65 );
66 }
67 }
68
69 if !owner_index.is_empty() {
70 bail!("owner_index: is missing entries: {owner_index:?}");
71 }
72 tracing::info!("Owner index is good");
73
74 for item in indexes.tables().coin_index().safe_iter() {
76 let (key, info) = item?;
77 let calculated_info = coin_index.remove(&key).ok_or_else(|| {
78 anyhow!(
79 "coin_index: found extra, unexpected entry {:?}",
80 (&key, &info)
81 )
82 })?;
83
84 if calculated_info != info {
85 bail!(
86 "coin_index: entry {key:?} is different: expected {calculated_info:?} found {info:?}"
87 );
88 }
89 }
90 tracing::info!("Coin index is good");
91
92 if !coin_index.is_empty() {
93 bail!("coin_index: is missing entries: {coin_index:?}");
94 }
95
96 info!("Finished running index verification checks");
97
98 Ok(())
99}