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