cfx_storage/impls/
state_manager.rs

1// Copyright 2019 Conflux Foundation. All rights reserved.
2// Conflux is free software and distributed under GNU General Public License.
3// See http://www.gnu.org/licenses/
4
5pub type DeltaDbManager = DeltaDbManagerRocksdb;
6pub type SnapshotDbManager = SnapshotDbManagerSqlite;
7pub type SnapshotDb = <SnapshotDbManager as SnapshotDbManagerTrait>::SnapshotDb;
8
9pub struct StateTrees {
10    pub snapshot_db: SnapshotDb,
11    pub snapshot_epoch_id: EpochId,
12    pub snapshot_merkle_root: MerkleHash,
13    /// None means that the intermediate_trie is empty, or in a special
14    /// situation that we use the snapshot at intermediate epoch directly,
15    /// so we don't need to look up intermediate trie.
16    pub maybe_intermediate_trie: Option<Arc<DeltaMpt>>,
17    pub intermediate_trie_root: Option<NodeRefDeltaMpt>,
18    pub intermediate_trie_root_merkle: MerkleHash,
19    /// A None value indicate the special case when snapshot_db is actually the
20    /// snapshot_db from the intermediate_epoch_id.
21    pub maybe_intermediate_trie_key_padding: Option<DeltaMptKeyPadding>,
22    /// Delta trie can't be none since we may commit into it.
23    pub delta_trie: Arc<DeltaMpt>,
24    pub delta_trie_root: Option<NodeRefDeltaMpt>,
25    pub delta_trie_key_padding: DeltaMptKeyPadding,
26    /// Information for making new snapshot when necessary.
27    pub maybe_delta_trie_height: Option<u32>,
28    pub maybe_height: Option<u64>,
29    pub intermediate_epoch_id: EpochId,
30
31    // TODO: this field is added only for the hack to get pivot chain from a
32    // TODO: snapshot to its parent snapshot.
33    pub parent_epoch_id: EpochId,
34}
35
36#[derive(MallocSizeOfDerive)]
37pub struct StateManager {
38    storage_manager: Arc<StorageManager>,
39    single_mpt_storage_manager: Option<Arc<SingleMptStorageManager>>,
40    pub number_committed_nodes: AtomicUsize,
41}
42
43impl Drop for StateManager {
44    fn drop(&mut self) { self.storage_manager.graceful_shutdown(); }
45}
46
47impl StateManager {
48    pub fn new(conf: StorageConfiguration) -> Result<Self> {
49        debug!("Storage conf {:?}", conf);
50        // Make sure sqlite temp directory is using the data disk instead of the
51        // system disk.
52        std::env::set_var("SQLITE_TMPDIR", conf.path_snapshot_dir.clone());
53
54        let single_mpt_storage_manager = if conf.enable_single_mpt_storage {
55            Some(SingleMptStorageManager::new_arc(
56                conf.path_storage_dir.join("single_mpt"),
57                conf.single_mpt_space,
58                conf.full_state_start_height().expect("enabled"),
59                conf.single_mpt_cache_start_size,
60                conf.single_mpt_cache_size,
61                conf.single_mpt_slab_idle_size,
62            ))
63        } else {
64            None
65        };
66
67        let storage_manager = StorageManager::new_arc(conf)?;
68        Ok(Self {
69            storage_manager,
70            single_mpt_storage_manager,
71            number_committed_nodes: Default::default(),
72        })
73    }
74
75    pub fn log_usage(&self) {
76        self.storage_manager.log_usage();
77        debug!(
78            "number of nodes committed to db {}",
79            self.number_committed_nodes.load(Ordering::Relaxed),
80        );
81    }
82
83    pub fn get_storage_manager(&self) -> &StorageManager {
84        &*self.storage_manager
85    }
86
87    pub fn get_storage_manager_arc(&self) -> &Arc<StorageManager> {
88        &self.storage_manager
89    }
90
91    /// delta_mpt_key_padding is required. When None is passed,
92    /// it's calculated for the state_trees.
93    #[inline]
94    pub fn get_state_trees_internal(
95        snapshot_db: SnapshotDb, snapshot_epoch_id: &EpochId,
96        snapshot_merkle_root: MerkleHash,
97        maybe_intermediate_trie: Option<Arc<DeltaMpt>>,
98        maybe_intermediate_trie_key_padding: Option<&DeltaMptKeyPadding>,
99        intermediate_epoch_id: &EpochId,
100        intermediate_trie_root_merkle: MerkleHash, delta_mpt: Arc<DeltaMpt>,
101        maybe_delta_mpt_key_padding: Option<&DeltaMptKeyPadding>,
102        epoch_id: &EpochId, delta_root: Option<NodeRefDeltaMpt>,
103        maybe_height: Option<u64>, maybe_delta_trie_height: Option<u32>,
104    ) -> Result<Option<StateTrees>> {
105        let intermediate_trie_root = match &maybe_intermediate_trie {
106            None => None,
107            Some(mpt) => {
108                match mpt.get_root_node_ref_by_epoch(intermediate_epoch_id)? {
109                    None => {
110                        warn!(
111                            "get_state_trees_internal, intermediate_mpt root not found \
112                             for epoch {:?}.",
113                            intermediate_epoch_id,
114                        );
115                        return Ok(None);
116                    }
117                    Some(root) => root,
118                }
119            }
120        };
121
122        let delta_trie_key_padding = match maybe_delta_mpt_key_padding {
123            Some(x) => x.clone(),
124            None => {
125                // TODO: maybe we can move the calculation to a central place
126                // and cache the result?
127                StorageKeyWithSpace::delta_mpt_padding(
128                    &snapshot_merkle_root,
129                    &intermediate_trie_root_merkle,
130                )
131            }
132        };
133
134        Ok(Some(StateTrees {
135            snapshot_db,
136            snapshot_merkle_root,
137            snapshot_epoch_id: *snapshot_epoch_id,
138            maybe_intermediate_trie,
139            intermediate_trie_root,
140            intermediate_trie_root_merkle,
141            maybe_intermediate_trie_key_padding:
142                maybe_intermediate_trie_key_padding.cloned(),
143            delta_trie: delta_mpt,
144            delta_trie_root: delta_root,
145            delta_trie_key_padding,
146            maybe_delta_trie_height,
147            maybe_height,
148            intermediate_epoch_id: intermediate_epoch_id.clone(),
149            parent_epoch_id: epoch_id.clone(),
150        }))
151    }
152
153    pub fn get_state_trees(
154        &self, state_index: &StateIndex, try_open: bool,
155        open_mpt_snapshot: bool,
156    ) -> Result<Option<StateTrees>> {
157        let maybe_intermediate_mpt;
158        let maybe_intermediate_mpt_key_padding;
159        let delta_mpt;
160        let snapshot;
161
162        match self.storage_manager.wait_for_snapshot(
163            &state_index.snapshot_epoch_id,
164            try_open,
165            open_mpt_snapshot,
166        )? {
167            None => {
168                // This is the special scenario when the snapshot isn't
169                // available but the snapshot at the intermediate epoch exists.
170                if let Some(guarded_snapshot) =
171                    self.storage_manager.wait_for_snapshot(
172                        &state_index.intermediate_epoch_id,
173                        try_open,
174                        open_mpt_snapshot,
175                    )?
176                {
177                    snapshot = guarded_snapshot;
178                    maybe_intermediate_mpt = None;
179                    maybe_intermediate_mpt_key_padding = None;
180                    delta_mpt = match self
181                        .storage_manager
182                        .get_intermediate_mpt(
183                            &state_index.intermediate_epoch_id,
184                        )? {
185                        None => {
186                            warn!(
187                                    "get_state_trees, special case, \
188                                    intermediate_mpt not found for epoch {:?}. StateIndex: {:?}.",
189                                    state_index.intermediate_epoch_id,
190                                    state_index,
191                                );
192                            return Ok(None);
193                        }
194                        Some(delta_mpt) => delta_mpt,
195                    };
196                } else {
197                    warn!(
198                        "get_state_trees, special case, \
199                         snapshot not found for epoch {:?}. StateIndex: {:?}.",
200                        state_index.intermediate_epoch_id, state_index,
201                    );
202                    return Ok(None);
203                }
204            }
205            Some(guarded_snapshot) => {
206                snapshot = guarded_snapshot;
207                maybe_intermediate_mpt_key_padding =
208                    state_index.maybe_intermediate_mpt_key_padding.as_ref();
209                maybe_intermediate_mpt = if maybe_intermediate_mpt_key_padding
210                    .is_some()
211                {
212                    self.storage_manager
213                        .get_intermediate_mpt(&state_index.snapshot_epoch_id)?
214                } else {
215                    None
216                };
217                delta_mpt = self
218                    .storage_manager
219                    .get_delta_mpt(&state_index.snapshot_epoch_id)?;
220            }
221        }
222
223        let delta_root = match delta_mpt
224            .get_root_node_ref_by_epoch(&state_index.epoch_id)?
225        {
226            None => {
227                debug!(
228                    "get_state_trees, \
229                    delta_root not found for epoch {:?}. mpt_id {}, StateIndex: {:?}.",
230                    state_index.epoch_id, delta_mpt.get_mpt_id(), state_index,
231                );
232                return Ok(None);
233            }
234            Some(root) => root,
235        };
236
237        Self::get_state_trees_internal(
238            snapshot.into().1,
239            &state_index.snapshot_epoch_id,
240            state_index.snapshot_merkle_root,
241            maybe_intermediate_mpt,
242            maybe_intermediate_mpt_key_padding,
243            &state_index.intermediate_epoch_id,
244            state_index.intermediate_trie_root_merkle,
245            delta_mpt,
246            Some(&state_index.delta_mpt_key_padding),
247            &state_index.epoch_id,
248            delta_root,
249            state_index.maybe_height,
250            state_index.maybe_delta_trie_height,
251        )
252    }
253
254    pub fn get_state_trees_for_next_epoch(
255        &self, parent_state_index: &StateIndex, try_open: bool,
256        open_mpt_snapshot: bool,
257    ) -> Result<Option<StateTrees>> {
258        let maybe_height = parent_state_index.maybe_height.map(|x| x + 1);
259
260        let snapshot;
261        let snapshot_epoch_id;
262        let snapshot_merkle_root;
263        let maybe_delta_trie_height;
264        let maybe_intermediate_mpt;
265        let maybe_intermediate_mpt_key_padding;
266        let intermediate_trie_root_merkle;
267        let delta_mpt;
268        let maybe_delta_mpt_key_padding;
269        let intermediate_epoch_id;
270        let new_delta_root;
271
272        if parent_state_index
273            .maybe_delta_trie_height
274            .unwrap_or_default()
275            == self.storage_manager.get_snapshot_epoch_count()
276        {
277            // Should shift to a new snapshot
278            // When the delta_height is set to None (e.g. in tests), we
279            // assume that the snapshot shift check is
280            // disabled.
281
282            snapshot_epoch_id = &parent_state_index.intermediate_epoch_id;
283            intermediate_epoch_id = &parent_state_index.epoch_id;
284            match self.storage_manager.wait_for_snapshot(
285                snapshot_epoch_id,
286                try_open,
287                open_mpt_snapshot,
288            )? {
289                None => {
290                    // This is the special scenario when the snapshot isn't
291                    // available but the snapshot at the intermediate epoch
292                    // exists.
293                    //
294                    // At the synced snapshot, the intermediate_epoch_id is
295                    // its parent snapshot. We need to shift again.
296
297                    // There is no snapshot_info for the parent snapshot,
298                    // how can we find out the snapshot_merkle_root?
299                    // See validate_blame_states().
300                    match self.storage_manager.wait_for_snapshot(
301                        &intermediate_epoch_id,
302                        try_open,
303                        open_mpt_snapshot,
304                    )? {
305                        None => {
306                            warn!(
307                                "get_state_trees_for_next_epoch, shift snapshot, special case, \
308                                snapshot not found for snapshot {:?}. StateIndex: {:?}.",
309                                parent_state_index.epoch_id,
310                                parent_state_index,
311                            );
312                            return Ok(None);
313                        }
314                        Some(guarded_snapshot) => {
315                            let (guard, _snapshot) = guarded_snapshot.into();
316                            snapshot_merkle_root =
317                                match StorageManager::find_merkle_root(
318                                    &guard,
319                                    snapshot_epoch_id,
320                                ) {
321                                    None => {
322                                        warn!(
323                                            "get_state_trees_for_next_epoch, shift snapshot, special case, \
324                                            snapshot merkel root not found for snapshot {:?}. StateIndex: {:?}.",
325                                            snapshot_epoch_id,
326                                            parent_state_index,
327                                        );
328                                        return Ok(None);
329                                    }
330                                    Some(merkle_root) => merkle_root,
331                                };
332
333                            snapshot = GuardedValue::new(guard, _snapshot);
334                        }
335                    }
336                    maybe_intermediate_mpt = None;
337                    maybe_intermediate_mpt_key_padding = None;
338                    match self
339                        .storage_manager
340                        .intermediate_trie_root_merkle
341                        .write()
342                        .take()
343                    {
344                        Some(v) => {
345                            intermediate_trie_root_merkle = v;
346                        }
347                        _ => {
348                            warn!(
349                                "get_state_trees_for_next_epoch, shift snapshot, special case, \
350                                intermediate_trie_root_merkle not found for snapshot {:?}. StateIndex: {:?}.",
351                                snapshot_epoch_id,
352                                parent_state_index,
353                            );
354                            return Ok(None);
355                        }
356                    }
357
358                    debug!("get_state_trees_for_next_epoch, snapshot_merkle_root {:?}, intermediate_trie_root_merkle {:?}", snapshot_merkle_root, intermediate_trie_root_merkle);
359
360                    match self
361                        .storage_manager
362                        .get_intermediate_mpt(&parent_state_index.epoch_id)?
363                    {
364                        None => {
365                            warn!(
366                                "get_state_trees_for_next_epoch, shift snapshot, special case, \
367                                intermediate_mpt not found for snapshot {:?}. StateIndex: {:?}.",
368                                parent_state_index.epoch_id,
369                                parent_state_index,
370                            );
371                            return Ok(None);
372                        }
373                        Some(mpt) => delta_mpt = mpt,
374                    }
375                }
376                Some(guarded_snapshot) => {
377                    let (guard, _snapshot) = guarded_snapshot.into();
378                    snapshot_merkle_root =
379                        match StorageManager::find_merkle_root(
380                            &guard,
381                            snapshot_epoch_id,
382                        ) {
383                            None => {
384                                warn!(
385                                "get_state_trees_for_next_epoch, shift snapshot, normal case, \
386                                snapshot info not found for snapshot {:?}. StateIndex: {:?}.",
387                                snapshot_epoch_id,
388                                parent_state_index,
389                            );
390                                return Ok(None);
391                            }
392                            Some(merkle_root) => merkle_root,
393                        };
394                    let guarded_snapshot = GuardedValue::new(guard, _snapshot);
395                    let temp_maybe_intermediate_mpt = self
396                        .storage_manager
397                        .get_intermediate_mpt(snapshot_epoch_id)?;
398                    match temp_maybe_intermediate_mpt {
399                        None => {
400                            snapshot = guarded_snapshot;
401                            maybe_intermediate_mpt_key_padding =
402                                Some(&parent_state_index.delta_mpt_key_padding);
403                            delta_mpt = self
404                                .storage_manager
405                                .get_delta_mpt(&snapshot_epoch_id)?;
406                            intermediate_trie_root_merkle = MERKLE_NULL_NODE;
407                            maybe_intermediate_mpt = None;
408                        }
409                        Some(mpt) => match mpt.get_merkle_root_by_epoch_id(
410                            &parent_state_index.epoch_id,
411                        )? {
412                            Some(merkle_root) => {
413                                snapshot = guarded_snapshot;
414                                maybe_intermediate_mpt_key_padding = Some(
415                                    &parent_state_index.delta_mpt_key_padding,
416                                );
417                                delta_mpt = self
418                                    .storage_manager
419                                    .get_delta_mpt(&snapshot_epoch_id)?;
420                                intermediate_trie_root_merkle = merkle_root;
421                                maybe_intermediate_mpt = Some(mpt);
422                            }
423                            None => {
424                                warn!(
425                                        "get_state_trees_for_next_epoch, shift snapshot, normal case, \
426                                        intermediate_trie_root not found for epoch {:?}. StateIndex: {:?}.",
427                                        parent_state_index.epoch_id,
428                                        parent_state_index,
429                                    );
430
431                                // Check if we should progress with a synced
432                                // state.
433                                // This is a quick fix for
434                                // https://github.com/Conflux-Chain/conflux-rust/issues/1543.
435                                // FIXME: We should remove all the hacks about
436                                // state sync.
437                                match self.storage_manager.wait_for_snapshot(
438                                    &parent_state_index.epoch_id,
439                                    try_open,
440                                    open_mpt_snapshot,
441                                )? {
442                                    None => {
443                                        warn!(
444                                            "get_state_trees_for_next_epoch, shift snapshot, special case, \
445                                snapshot not found for snapshot {:?}. StateIndex: {:?}.",
446                                            parent_state_index.epoch_id,
447                                            parent_state_index,
448                                        );
449                                        return Ok(None);
450                                    }
451                                    Some(guarded_synced_snapshot) => {
452                                        snapshot = guarded_synced_snapshot;
453                                    }
454                                }
455                                maybe_intermediate_mpt = None;
456                                maybe_intermediate_mpt_key_padding = None;
457                                match self
458                                    .storage_manager
459                                    .intermediate_trie_root_merkle
460                                    .write()
461                                    .take()
462                                {
463                                    Some(v) => {
464                                        intermediate_trie_root_merkle = v;
465                                    }
466                                    _ => {
467                                        warn!("get_state_trees_for_next_epoch, shift snapshot, special case, \
468                                        intermediate_trie_root_merkle not found for snapshot {:?}. StateIndex: {:?}.", snapshot_epoch_id, parent_state_index,);
469                                        return Ok(None);
470                                    }
471                                }
472
473                                match self
474                                    .storage_manager
475                                    .get_intermediate_mpt(
476                                        &parent_state_index.epoch_id,
477                                    )? {
478                                    None => {
479                                        warn!(
480                                            "get_state_trees_for_next_epoch, shift snapshot, special case, \
481                                intermediate_mpt not found for snapshot {:?}. StateIndex: {:?}.",
482                                            parent_state_index.epoch_id,
483                                            parent_state_index,
484                                        );
485                                        return Ok(None);
486                                    }
487                                    Some(mpt) => delta_mpt = mpt,
488                                }
489                            }
490                        },
491                    };
492                }
493            };
494            maybe_delta_mpt_key_padding = None;
495            maybe_delta_trie_height = Some(1);
496            new_delta_root = true;
497        } else {
498            snapshot_epoch_id = &parent_state_index.snapshot_epoch_id;
499            snapshot_merkle_root = parent_state_index.snapshot_merkle_root;
500            intermediate_epoch_id = &parent_state_index.intermediate_epoch_id;
501            intermediate_trie_root_merkle =
502                parent_state_index.intermediate_trie_root_merkle;
503            match self.storage_manager.wait_for_snapshot(
504                snapshot_epoch_id,
505                try_open,
506                open_mpt_snapshot,
507            )? {
508                None => {
509                    // This is the special scenario when the snapshot isn't
510                    // available but the snapshot at the intermediate epoch
511                    // exists.
512                    if let Some(guarded_snapshot) =
513                        self.storage_manager.wait_for_snapshot(
514                            &intermediate_epoch_id,
515                            try_open,
516                            open_mpt_snapshot,
517                        )?
518                    {
519                        snapshot = guarded_snapshot;
520                        maybe_intermediate_mpt = None;
521                        maybe_intermediate_mpt_key_padding = None;
522                        delta_mpt = match self
523                            .storage_manager
524                            .get_intermediate_mpt(intermediate_epoch_id)?
525                        {
526                            None => {
527                                return {
528                                    warn!(
529                                    "get_state_trees_for_next_epoch, special case, \
530                                    intermediate_mpt not found for epoch {:?}. StateIndex: {:?}.",
531                                    intermediate_epoch_id,
532                                    parent_state_index,
533                                );
534                                    Ok(None)
535                                }
536                            }
537                            Some(delta_mpt) => delta_mpt,
538                        };
539                    } else {
540                        warn!(
541                            "get_state_trees_for_next_epoch, special case, \
542                            snapshot not found for epoch {:?}. StateIndex: {:?}.",
543                            intermediate_epoch_id,
544                            parent_state_index,
545                        );
546                        return Ok(None);
547                    }
548                }
549                Some(guarded_snapshot) => {
550                    snapshot = guarded_snapshot;
551                    maybe_intermediate_mpt_key_padding = parent_state_index
552                        .maybe_intermediate_mpt_key_padding
553                        .as_ref();
554                    maybe_intermediate_mpt =
555                        if maybe_intermediate_mpt_key_padding.is_some() {
556                            self.storage_manager
557                                .get_intermediate_mpt(snapshot_epoch_id)?
558                        } else {
559                            None
560                        };
561                    delta_mpt = self
562                        .storage_manager
563                        .get_delta_mpt(snapshot_epoch_id)?;
564                }
565            };
566            maybe_delta_trie_height =
567                parent_state_index.maybe_delta_trie_height.map(|x| x + 1);
568            maybe_delta_mpt_key_padding =
569                Some(&parent_state_index.delta_mpt_key_padding);
570            new_delta_root = false;
571        };
572
573        let delta_root = if new_delta_root {
574            None
575        } else {
576            match delta_mpt
577                .get_root_node_ref_by_epoch(&parent_state_index.epoch_id)?
578            {
579                None => {
580                    warn!(
581                        "get_state_trees_for_next_epoch, not shifting, \
582                         delta_root not found for epoch {:?}. mpt_id {}, StateIndex: {:?}.",
583                        parent_state_index.epoch_id,
584                        delta_mpt.get_mpt_id(), parent_state_index
585                    );
586                    return Ok(None);
587                }
588                Some(root_node) => root_node,
589            }
590        };
591        Self::get_state_trees_internal(
592            snapshot.into().1,
593            snapshot_epoch_id,
594            snapshot_merkle_root,
595            maybe_intermediate_mpt,
596            maybe_intermediate_mpt_key_padding,
597            intermediate_epoch_id,
598            intermediate_trie_root_merkle,
599            delta_mpt,
600            maybe_delta_mpt_key_padding,
601            &parent_state_index.epoch_id,
602            delta_root,
603            maybe_height,
604            maybe_delta_trie_height,
605        )
606    }
607
608    /// Check if we can make a new snapshot, and if so, make it in background.
609    pub fn check_make_snapshot(
610        &self, maybe_intermediate_trie: Option<Arc<DeltaMpt>>,
611        intermediate_trie_root: Option<NodeRefDeltaMpt>,
612        intermediate_epoch_id: &EpochId, new_height: u64,
613        recover_mpt_during_construct_pivot_state: bool,
614    ) -> Result<()> {
615        StorageManager::check_make_register_snapshot_background(
616            self.storage_manager.clone(),
617            intermediate_epoch_id.clone(),
618            new_height,
619            maybe_intermediate_trie.map(|intermediate_trie| DeltaMptIterator {
620                mpt: intermediate_trie,
621                maybe_root_node: intermediate_trie_root,
622            }),
623            recover_mpt_during_construct_pivot_state,
624        )
625    }
626
627    pub fn get_state_no_commit_inner(
628        self: &Arc<Self>, state_index: StateIndex, try_open: bool,
629        open_mpt_snapshot: bool,
630    ) -> Result<Option<State>> {
631        let maybe_state_trees =
632            self.get_state_trees(&state_index, try_open, open_mpt_snapshot)?;
633        match maybe_state_trees {
634            None => Ok(None),
635            Some(state_trees) => {
636                Ok(Some(State::new(self.clone(), state_trees, false)))
637            }
638        }
639    }
640
641    fn get_state_for_genesis_write_inner(self: &Arc<Self>) -> State {
642        State::new(
643            self.clone(),
644            StateTrees {
645                snapshot_db: self
646                    .storage_manager
647                    .wait_for_snapshot(
648                        &NULL_EPOCH,
649                        /* try_open = */ false,
650                        true,
651                    )
652                    .unwrap()
653                    .unwrap()
654                    .into()
655                    .1,
656                snapshot_epoch_id: NULL_EPOCH,
657                snapshot_merkle_root: MERKLE_NULL_NODE,
658                maybe_intermediate_trie: None,
659                intermediate_trie_root: None,
660                intermediate_trie_root_merkle: MERKLE_NULL_NODE,
661                maybe_intermediate_trie_key_padding: None,
662                delta_trie: self
663                    .storage_manager
664                    .get_delta_mpt(&NULL_EPOCH)
665                    .unwrap(),
666                delta_trie_root: None,
667                delta_trie_key_padding: GENESIS_DELTA_MPT_KEY_PADDING.clone(),
668                maybe_delta_trie_height: Some(1),
669                maybe_height: Some(1),
670                intermediate_epoch_id: NULL_EPOCH,
671                parent_epoch_id: NULL_EPOCH,
672            },
673            false,
674        )
675    }
676
677    // Currently we use epoch number to decide whether or not to
678    // start a new delta trie. The value of parent_epoch_id is only
679    // known after the computation is done.
680    //
681    // If we use delta trie size upper bound to decide whether or not
682    // to start a new delta trie, then the computation about whether
683    // or not start a new delta trie, can only be done at the time
684    // of committing. In this scenario, the execution engine should
685    // first get the state assuming that the delta trie won't change,
686    // then check if committing fails due to over size, and if so,
687    // start a new delta trie and re-apply the change.
688    //
689    // Due to the complexity of the latter approach, we stay with the
690    // simple approach.
691    pub fn get_state_for_next_epoch_inner(
692        self: &Arc<Self>, parent_epoch_id: StateIndex, open_mpt_snapshot: bool,
693        recover_mpt_during_construct_pivot_state: bool,
694    ) -> Result<Option<State>> {
695        let maybe_state_trees = self.get_state_trees_for_next_epoch(
696            &parent_epoch_id,
697            /* try_open = */ false,
698            open_mpt_snapshot,
699        )?;
700        match maybe_state_trees {
701            None => Ok(None),
702            Some(state_trees) => Ok(Some(State::new(
703                self.clone(),
704                state_trees,
705                recover_mpt_during_construct_pivot_state,
706            ))),
707        }
708    }
709
710    pub fn notify_genesis_hash(&self, genesis_hash: EpochId) {
711        if let Some(single_mpt_manager) = &self.single_mpt_storage_manager {
712            *single_mpt_manager.genesis_hash.lock() = genesis_hash;
713        }
714    }
715
716    pub fn config(&self) -> &StorageConfiguration {
717        &self.storage_manager.storage_conf
718    }
719}
720
721impl StateManagerTrait for StateManager {
722    fn get_state_no_commit(
723        self: &Arc<Self>, state_index: StateIndex, try_open: bool,
724        space: Option<Space>,
725    ) -> Result<Option<Box<dyn StateTrait>>> {
726        let maybe_state_trees =
727            self.get_state_trees(&state_index, try_open, false);
728        // If there is an error, we will continue to search for an available
729        // single_mpt.
730        let maybe_state_err = match maybe_state_trees {
731            Ok(Some(state_trees)) => {
732                return Ok(Some(Box::new(State::new(
733                    self.clone(),
734                    state_trees,
735                    false,
736                ))));
737            }
738            Err(e) => Err(e),
739            Ok(None) => Ok(None),
740        };
741        if self.single_mpt_storage_manager.is_none() {
742            return maybe_state_err;
743        }
744        let single_mpt_storage_manager =
745            self.single_mpt_storage_manager.as_ref().unwrap();
746        if !single_mpt_storage_manager.contains_space(&space) {
747            return maybe_state_err;
748        }
749        debug!(
750            "read state from single mpt state: epoch={}",
751            state_index.epoch_id
752        );
753        let single_mpt_state = single_mpt_storage_manager
754            .get_state_by_epoch(state_index.epoch_id)?;
755        if single_mpt_state.is_none() {
756            warn!("single mpt state missing: epoch={:?}", state_index.epoch_id);
757            return maybe_state_err;
758        } else {
759            Ok(Some(Box::new(single_mpt_state.unwrap())))
760        }
761    }
762
763    fn get_state_for_genesis_write(self: &Arc<Self>) -> Box<dyn StateTrait> {
764        let state = self.get_state_for_genesis_write_inner();
765        if self.single_mpt_storage_manager.is_none() {
766            return Box::new(state);
767        }
768        let single_mpt_storage_manager =
769            self.single_mpt_storage_manager.as_ref().unwrap();
770        let single_mpt_state = single_mpt_storage_manager
771            .get_state_for_genesis()
772            .expect("single_mpt genesis initialize error");
773        Box::new(ReplicatedState::new(
774            state,
775            single_mpt_state,
776            single_mpt_storage_manager.get_state_filter(),
777        ))
778    }
779
780    // Currently we use epoch number to decide whether or not to
781    // start a new delta trie. The value of parent_epoch_id is only
782    // known after the computation is done.
783    //
784    // If we use delta trie size upper bound to decide whether or not
785    // to start a new delta trie, then the computation about whether
786    // or not start a new delta trie, can only be done at the time
787    // of committing. In this scenario, the execution engine should
788    // first get the state assuming that the delta trie won't change,
789    // then check if committing fails due to over size, and if so,
790    // start a new delta trie and re-apply the change.
791    //
792    // Due to the complexity of the latter approach, we stay with the
793    // simple approach.
794    fn get_state_for_next_epoch(
795        self: &Arc<Self>, parent_epoch_id: StateIndex,
796        recover_mpt_during_construct_pivot_state: bool,
797    ) -> Result<Option<Box<dyn StateTrait>>> {
798        let mut parent_epoch = parent_epoch_id.epoch_id;
799        let parent_height = parent_epoch_id.maybe_height;
800        let state = self.get_state_for_next_epoch_inner(
801            parent_epoch_id,
802            false,
803            recover_mpt_during_construct_pivot_state,
804        )?;
805        if state.is_none() {
806            return Ok(None);
807        }
808        if self.single_mpt_storage_manager.is_none() {
809            return Ok(Some(Box::new(state.unwrap())));
810        }
811        let single_mpt_storage_manager =
812            self.single_mpt_storage_manager.as_ref().unwrap();
813        if let Some(parent_height) = parent_height {
814            trace!(
815                "get_state_for_next_epoch: parent={}, available={}",
816                parent_height,
817                single_mpt_storage_manager.available_height
818            );
819            if single_mpt_storage_manager.available_height > parent_height {
820                return Ok(Some(Box::new(state.unwrap())));
821            } else if single_mpt_storage_manager.available_height
822                == parent_height
823            {
824                // For the first available single_mpt state, we read the genesis
825                // block state as the parent state to continue execution.
826                // This is only needed for tests because there is no eSpace
827                // state entries for Conflux Mainnet.
828                parent_epoch = *single_mpt_storage_manager.genesis_hash.lock();
829            }
830        }
831        let single_mpt_state =
832            single_mpt_storage_manager.get_state_by_epoch(parent_epoch)?;
833        if single_mpt_state.is_none() {
834            error!("get_state_for_next_epoch: single_mpt_state is required but is not found!");
835            return Ok(None);
836        }
837        Ok(Some(Box::new(ReplicatedState::new(
838            state.unwrap(),
839            single_mpt_state.unwrap(),
840            single_mpt_storage_manager.get_state_filter(),
841        ))))
842    }
843}
844
845use crate::{
846    impls::{
847        delta_mpt::*,
848        errors::*,
849        replicated_state::ReplicatedState,
850        storage_db::{
851            delta_db_manager_rocksdb::DeltaDbManagerRocksdb,
852            snapshot_db_manager_sqlite::SnapshotDbManagerSqlite,
853        },
854        storage_manager::{
855            single_mpt_storage_manager::SingleMptStorageManager,
856            storage_manager::StorageManager,
857        },
858    },
859    state::*,
860    state_manager::*,
861    storage_db::*,
862    utils::guarded_value::GuardedValue,
863    StorageConfiguration,
864};
865use cfx_types::Space;
866use malloc_size_of_derive::MallocSizeOf as MallocSizeOfDerive;
867use primitives::{
868    DeltaMptKeyPadding, EpochId, MerkleHash, StorageKeyWithSpace,
869    GENESIS_DELTA_MPT_KEY_PADDING, MERKLE_NULL_NODE, NULL_EPOCH,
870};
871use std::sync::{
872    atomic::{AtomicUsize, Ordering},
873    Arc,
874};