1use std::collections::{BTreeMap, HashMap};
6
7use iota_config::genesis;
8use iota_types::{
9 base_types::{AuthorityName, IotaAddress, ObjectID, SequenceNumber},
10 committee::{Committee, EpochId},
11 crypto::{AccountKeyPair, AuthorityKeyPair},
12 digests::{ObjectDigest, TransactionDigest, TransactionEventsDigest},
13 effects::{TransactionEffects, TransactionEffectsAPI, TransactionEvents},
14 error::IotaError,
15 messages_checkpoint::{
16 CheckpointContents, CheckpointContentsDigest, CheckpointDigest, CheckpointSequenceNumber,
17 VerifiedCheckpoint,
18 },
19 object::{Object, Owner},
20 storage::{
21 BackingPackageStore, ChildObjectResolver, ObjectStore, PackageObject, get_module,
22 load_package_object_from_object_store,
23 },
24 transaction::VerifiedTransaction,
25};
26use move_binary_format::CompiledModule;
27use move_bytecode_utils::module_cache::GetModule;
28use move_core_types::{language_storage::ModuleId, resolver::ModuleResolver};
29
30use super::SimulatorStore;
31
32#[derive(Debug, Default)]
33pub struct InMemoryStore {
34 checkpoints: BTreeMap<CheckpointSequenceNumber, VerifiedCheckpoint>,
36 checkpoint_digest_to_sequence_number: HashMap<CheckpointDigest, CheckpointSequenceNumber>,
37 checkpoint_contents: HashMap<CheckpointContentsDigest, CheckpointContents>,
38
39 transactions: HashMap<TransactionDigest, VerifiedTransaction>,
41 effects: HashMap<TransactionDigest, TransactionEffects>,
42 events: HashMap<TransactionEventsDigest, TransactionEvents>,
43 events_tx_digest_index: HashMap<TransactionDigest, TransactionEventsDigest>,
45
46 epoch_to_committee: Vec<Committee>,
48
49 live_objects: HashMap<ObjectID, SequenceNumber>,
51 objects: HashMap<ObjectID, BTreeMap<SequenceNumber, Object>>,
52}
53
54impl InMemoryStore {
55 pub fn new(genesis: &genesis::Genesis) -> Self {
56 let mut store = Self::default();
57 store.init_with_genesis(genesis);
58 store
59 }
60
61 pub fn get_checkpoint_by_sequence_number(
62 &self,
63 sequence_number: CheckpointSequenceNumber,
64 ) -> Option<&VerifiedCheckpoint> {
65 self.checkpoints.get(&sequence_number)
66 }
67
68 pub fn get_checkpoint_by_digest(
69 &self,
70 digest: &CheckpointDigest,
71 ) -> Option<&VerifiedCheckpoint> {
72 self.checkpoint_digest_to_sequence_number
73 .get(digest)
74 .and_then(|sequence_number| self.get_checkpoint_by_sequence_number(*sequence_number))
75 }
76
77 pub fn get_highest_checkpoint(&self) -> Option<&VerifiedCheckpoint> {
78 self.checkpoints
79 .last_key_value()
80 .map(|(_, checkpoint)| checkpoint)
81 }
82
83 pub fn get_checkpoint_contents(
84 &self,
85 digest: &CheckpointContentsDigest,
86 ) -> Option<&CheckpointContents> {
87 self.checkpoint_contents.get(digest)
88 }
89
90 pub fn get_committee_by_epoch(&self, epoch: EpochId) -> Option<&Committee> {
91 self.epoch_to_committee.get(epoch as usize)
92 }
93 pub fn get_transaction(&self, digest: &TransactionDigest) -> Option<&VerifiedTransaction> {
94 self.transactions.get(digest)
95 }
96
97 pub fn get_transaction_effects(
98 &self,
99 digest: &TransactionDigest,
100 ) -> Option<&TransactionEffects> {
101 self.effects.get(digest)
102 }
103
104 pub fn get_transaction_events(
105 &self,
106 digest: &TransactionEventsDigest,
107 ) -> Option<&TransactionEvents> {
108 self.events.get(digest)
109 }
110
111 pub fn get_object(&self, id: &ObjectID) -> Option<&Object> {
112 let version = self.live_objects.get(id)?;
113 self.get_object_at_version(id, *version)
114 }
115
116 pub fn get_object_at_version(&self, id: &ObjectID, version: SequenceNumber) -> Option<&Object> {
117 self.objects
118 .get(id)
119 .and_then(|versions| versions.get(&version))
120 }
121
122 pub fn get_system_state(&self) -> iota_types::iota_system_state::IotaSystemState {
123 iota_types::iota_system_state::get_iota_system_state(self).expect("system state must exist")
124 }
125
126 pub fn get_clock(&self) -> iota_types::clock::Clock {
127 self.get_object(&iota_types::IOTA_CLOCK_OBJECT_ID)
128 .expect("clock should exist")
129 .to_rust()
130 .expect("clock object should deserialize")
131 }
132
133 pub fn owned_objects(&self, owner: IotaAddress) -> impl Iterator<Item = &Object> {
134 self.live_objects
135 .iter()
136 .flat_map(|(id, version)| self.get_object_at_version(id, *version))
137 .filter(
138 move |object| matches!(object.owner, Owner::AddressOwner(addr) if addr == owner),
139 )
140 }
141}
142
143impl InMemoryStore {
144 pub fn insert_checkpoint(&mut self, checkpoint: VerifiedCheckpoint) {
145 if let Some(end_of_epoch_data) = &checkpoint.data().end_of_epoch_data {
146 let next_committee = end_of_epoch_data
147 .next_epoch_committee
148 .iter()
149 .cloned()
150 .collect();
151 let committee =
152 Committee::new(checkpoint.epoch().checked_add(1).unwrap(), next_committee);
153 self.insert_committee(committee);
154 }
155
156 self.checkpoint_digest_to_sequence_number
157 .insert(*checkpoint.digest(), *checkpoint.sequence_number());
158 self.checkpoints
159 .insert(*checkpoint.sequence_number(), checkpoint);
160 }
161
162 pub fn insert_checkpoint_contents(&mut self, contents: CheckpointContents) {
163 self.checkpoint_contents
164 .insert(*contents.digest(), contents);
165 }
166
167 pub fn insert_committee(&mut self, committee: Committee) {
168 let epoch = committee.epoch as usize;
169
170 if self.epoch_to_committee.get(epoch).is_some() {
171 return;
172 }
173
174 if self.epoch_to_committee.len() == epoch {
175 self.epoch_to_committee.push(committee);
176 } else {
177 panic!("committee was inserted into EpochCommitteeMap out of order");
178 }
179 }
180
181 pub fn insert_executed_transaction(
182 &mut self,
183 transaction: VerifiedTransaction,
184 effects: TransactionEffects,
185 events: TransactionEvents,
186 written_objects: BTreeMap<ObjectID, Object>,
187 ) {
188 let deleted_objects = effects.deleted();
189 let tx_digest = *effects.transaction_digest();
190 self.insert_transaction(transaction);
191 self.insert_transaction_effects(effects);
192 self.insert_events(&tx_digest, events);
193 self.update_objects(written_objects, deleted_objects);
194 }
195
196 pub fn insert_transaction(&mut self, transaction: VerifiedTransaction) {
197 self.transactions.insert(*transaction.digest(), transaction);
198 }
199
200 pub fn insert_transaction_effects(&mut self, effects: TransactionEffects) {
201 self.effects.insert(*effects.transaction_digest(), effects);
202 }
203
204 pub fn insert_events(&mut self, tx_digest: &TransactionDigest, events: TransactionEvents) {
205 self.events_tx_digest_index
206 .insert(*tx_digest, events.digest());
207 self.events.insert(events.digest(), events);
208 }
209
210 pub fn update_objects(
211 &mut self,
212 written_objects: BTreeMap<ObjectID, Object>,
213 deleted_objects: Vec<(ObjectID, SequenceNumber, ObjectDigest)>,
214 ) {
215 for (object_id, _, _) in deleted_objects {
216 self.live_objects.remove(&object_id);
217 }
218
219 for (object_id, object) in written_objects {
220 let version = object.version();
221 self.live_objects.insert(object_id, version);
222 self.objects
223 .entry(object_id)
224 .or_default()
225 .insert(version, object);
226 }
227 }
228}
229
230impl BackingPackageStore for InMemoryStore {
231 fn get_package_object(
232 &self,
233 package_id: &ObjectID,
234 ) -> iota_types::error::IotaResult<Option<PackageObject>> {
235 load_package_object_from_object_store(self, package_id)
236 }
237}
238
239impl ChildObjectResolver for InMemoryStore {
240 fn read_child_object(
241 &self,
242 parent: &ObjectID,
243 child: &ObjectID,
244 child_version_upper_bound: SequenceNumber,
245 ) -> iota_types::error::IotaResult<Option<Object>> {
246 let child_object = match crate::store::SimulatorStore::get_object(self, child) {
247 None => return Ok(None),
248 Some(obj) => obj,
249 };
250
251 let parent = *parent;
252 if child_object.owner != Owner::ObjectOwner(parent.into()) {
253 return Err(IotaError::InvalidChildObjectAccess {
254 object: *child,
255 given_parent: parent,
256 actual_owner: child_object.owner,
257 });
258 }
259
260 if child_object.version() > child_version_upper_bound {
261 return Err(IotaError::UnsupportedFeature {
262 error: "TODO InMemoryStorage::read_child_object does not yet support bounded reads"
263 .to_owned(),
264 });
265 }
266
267 Ok(Some(child_object))
268 }
269
270 fn get_object_received_at_version(
271 &self,
272 owner: &ObjectID,
273 receiving_object_id: &ObjectID,
274 receive_object_at_version: SequenceNumber,
275 _epoch_id: EpochId,
276 ) -> iota_types::error::IotaResult<Option<Object>> {
277 let recv_object = match crate::store::SimulatorStore::get_object(self, receiving_object_id)
278 {
279 None => return Ok(None),
280 Some(obj) => obj,
281 };
282 if recv_object.owner != Owner::AddressOwner((*owner).into()) {
283 return Ok(None);
284 }
285
286 if recv_object.version() != receive_object_at_version {
287 return Ok(None);
288 }
289 Ok(Some(recv_object))
290 }
291}
292
293impl GetModule for InMemoryStore {
294 type Error = IotaError;
295 type Item = CompiledModule;
296
297 fn get_module_by_id(&self, id: &ModuleId) -> Result<Option<Self::Item>, Self::Error> {
298 Ok(self
299 .get_module(id)?
300 .map(|bytes| CompiledModule::deserialize_with_defaults(&bytes).unwrap()))
301 }
302}
303
304impl ModuleResolver for InMemoryStore {
305 type Error = IotaError;
306
307 fn get_module(&self, module_id: &ModuleId) -> Result<Option<Vec<u8>>, Self::Error> {
308 get_module(self, module_id)
309 }
310}
311
312impl ObjectStore for InMemoryStore {
313 fn get_object(
314 &self,
315 object_id: &ObjectID,
316 ) -> Result<Option<Object>, iota_types::storage::error::Error> {
317 Ok(self.get_object(object_id).cloned())
318 }
319
320 fn get_object_by_key(
321 &self,
322 object_id: &ObjectID,
323 version: iota_types::base_types::VersionNumber,
324 ) -> Result<Option<Object>, iota_types::storage::error::Error> {
325 Ok(self.get_object_at_version(object_id, version).cloned())
326 }
327}
328
329#[derive(Debug)]
330pub struct KeyStore {
331 validator_keys: BTreeMap<AuthorityName, AuthorityKeyPair>,
332 account_keys: BTreeMap<IotaAddress, AccountKeyPair>,
333}
334
335impl KeyStore {
336 pub fn from_network_config(
337 network_config: &iota_swarm_config::network_config::NetworkConfig,
338 ) -> Self {
339 use fastcrypto::traits::KeyPair;
340
341 let validator_keys = network_config
342 .validator_configs()
343 .iter()
344 .map(|config| {
345 (
346 config.authority_public_key(),
347 config.authority_key_pair().copy(),
348 )
349 })
350 .collect();
351
352 let account_keys = network_config
353 .account_keys
354 .iter()
355 .map(|key| (key.public().into(), key.copy()))
356 .collect();
357 Self {
358 validator_keys,
359 account_keys,
360 }
361 }
362
363 pub fn validator(&self, name: &AuthorityName) -> Option<&AuthorityKeyPair> {
364 self.validator_keys.get(name)
365 }
366
367 pub fn accounts(&self) -> impl Iterator<Item = (&IotaAddress, &AccountKeyPair)> {
368 self.account_keys.iter()
369 }
370}
371
372impl SimulatorStore for InMemoryStore {
373 fn get_checkpoint_by_sequence_number(
374 &self,
375 sequence_number: CheckpointSequenceNumber,
376 ) -> Option<VerifiedCheckpoint> {
377 self.get_checkpoint_by_sequence_number(sequence_number)
378 .cloned()
379 }
380
381 fn get_checkpoint_by_digest(&self, digest: &CheckpointDigest) -> Option<VerifiedCheckpoint> {
382 self.get_checkpoint_by_digest(digest).cloned()
383 }
384
385 fn get_highest_checkpoint(&self) -> Option<VerifiedCheckpoint> {
386 self.get_highest_checkpoint().cloned()
387 }
388
389 fn get_checkpoint_contents(
390 &self,
391 digest: &CheckpointContentsDigest,
392 ) -> Option<CheckpointContents> {
393 self.get_checkpoint_contents(digest).cloned()
394 }
395
396 fn get_committee_by_epoch(&self, epoch: EpochId) -> Option<Committee> {
397 self.get_committee_by_epoch(epoch).cloned()
398 }
399
400 fn get_transaction(&self, digest: &TransactionDigest) -> Option<VerifiedTransaction> {
401 self.get_transaction(digest).cloned()
402 }
403
404 fn get_transaction_effects(&self, digest: &TransactionDigest) -> Option<TransactionEffects> {
405 self.get_transaction_effects(digest).cloned()
406 }
407
408 fn get_transaction_events(
409 &self,
410 digest: &TransactionEventsDigest,
411 ) -> Option<TransactionEvents> {
412 self.get_transaction_events(digest).cloned()
413 }
414
415 fn get_transaction_events_by_tx_digest(
416 &self,
417 tx_digest: &TransactionDigest,
418 ) -> Option<TransactionEvents> {
419 self.events_tx_digest_index
420 .get(tx_digest)
421 .and_then(|x| self.events.get(x))
422 .cloned()
423 }
424
425 fn get_object(&self, id: &ObjectID) -> Option<Object> {
426 self.get_object(id).cloned()
427 }
428
429 fn get_object_at_version(&self, id: &ObjectID, version: SequenceNumber) -> Option<Object> {
430 self.get_object_at_version(id, version).cloned()
431 }
432
433 fn get_system_state(&self) -> iota_types::iota_system_state::IotaSystemState {
434 self.get_system_state()
435 }
436
437 fn get_clock(&self) -> iota_types::clock::Clock {
438 self.get_clock()
439 }
440
441 fn owned_objects(&self, owner: IotaAddress) -> Box<dyn Iterator<Item = Object> + '_> {
442 Box::new(self.owned_objects(owner).cloned())
443 }
444
445 fn insert_checkpoint(&mut self, checkpoint: VerifiedCheckpoint) {
446 self.insert_checkpoint(checkpoint)
447 }
448
449 fn insert_checkpoint_contents(&mut self, contents: CheckpointContents) {
450 self.insert_checkpoint_contents(contents)
451 }
452
453 fn insert_committee(&mut self, committee: Committee) {
454 self.insert_committee(committee)
455 }
456
457 fn insert_executed_transaction(
458 &mut self,
459 transaction: VerifiedTransaction,
460 effects: TransactionEffects,
461 events: TransactionEvents,
462 written_objects: BTreeMap<ObjectID, Object>,
463 ) {
464 self.insert_executed_transaction(transaction, effects, events, written_objects)
465 }
466
467 fn insert_transaction(&mut self, transaction: VerifiedTransaction) {
468 self.insert_transaction(transaction)
469 }
470
471 fn insert_transaction_effects(&mut self, effects: TransactionEffects) {
472 self.insert_transaction_effects(effects)
473 }
474
475 fn insert_events(&mut self, tx_digest: &TransactionDigest, events: TransactionEvents) {
476 self.insert_events(tx_digest, events)
477 }
478
479 fn update_objects(
480 &mut self,
481 written_objects: BTreeMap<ObjectID, Object>,
482 deleted_objects: Vec<(ObjectID, SequenceNumber, ObjectDigest)>,
483 ) {
484 self.update_objects(written_objects, deleted_objects)
485 }
486
487 fn backing_store(&self) -> &dyn iota_types::storage::BackingStore {
488 self
489 }
490}