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