cfxcore/pos/state_sync/
shared_components.rs

1// Copyright (c) The Diem Core Contributors
2// SPDX-License-Identifier: Apache-2.0
3
4// Copyright 2021 Conflux Foundation. All rights reserved.
5// Conflux is free software and distributed under GNU General Public License.
6// See http://www.gnu.org/licenses/
7
8use super::error::Error;
9use diem_types::{
10    epoch_change::Verifier, epoch_state::EpochState,
11    ledger_info::LedgerInfoWithSignatures,
12};
13use executor_types::ExecutedTrees;
14
15/// SyncState contains the following fields:
16/// * `committed_ledger_info` holds the latest certified ledger info (committed
17///   to storage), i.e., the ledger info for the highest version for which
18///   storage has all ledger state.
19/// * `synced_trees` holds the latest transaction accumulator and state tree
20///   (which may or may not be committed to storage), i.e., some ledger state
21///   for the next highest ledger info version is missing.
22/// * `trusted_epoch_state` corresponds to the current epoch if the highest
23///   committed ledger info (`committed_ledger_info`) is in the middle of the
24///   epoch, otherwise, it corresponds to the next epoch if the highest
25///   committed ledger info ends the epoch.
26///
27/// Note: `committed_ledger_info` is used for helping other Diem nodes
28/// synchronize (i.e., it corresponds to the highest version we have a proof for
29/// in storage). `synced_trees` is used locally for retrieving missing chunks
30/// for the local storage.
31#[derive(Clone, Debug)]
32pub struct SyncState {
33    committed_ledger_info: LedgerInfoWithSignatures,
34    synced_trees: ExecutedTrees,
35    trusted_epoch_state: EpochState,
36}
37
38impl SyncState {
39    pub fn new(
40        committed_ledger_info: LedgerInfoWithSignatures,
41        synced_trees: ExecutedTrees, current_epoch_state: EpochState,
42    ) -> Self {
43        let trusted_epoch_state = committed_ledger_info
44            .ledger_info()
45            .next_epoch_state()
46            .cloned()
47            .unwrap_or(current_epoch_state);
48
49        SyncState {
50            committed_ledger_info,
51            synced_trees,
52            trusted_epoch_state,
53        }
54    }
55
56    pub fn committed_epoch(&self) -> u64 {
57        self.committed_ledger_info.ledger_info().epoch()
58    }
59
60    pub fn committed_ledger_info(&self) -> LedgerInfoWithSignatures {
61        self.committed_ledger_info.clone()
62    }
63
64    pub fn committed_version(&self) -> u64 {
65        self.committed_ledger_info.ledger_info().version()
66    }
67
68    /// Returns the highest available version in the local storage, even if it's
69    /// not committed (i.e., covered by a ledger info).
70    pub fn synced_version(&self) -> u64 {
71        self.synced_trees.version().unwrap_or(0)
72    }
73
74    pub fn trusted_epoch(&self) -> u64 { self.trusted_epoch_state.epoch }
75
76    pub fn verify_ledger_info(
77        &self, ledger_info: &LedgerInfoWithSignatures,
78    ) -> Result<(), Error> {
79        self.trusted_epoch_state
80            .verify(ledger_info)
81            .map_err(|error| Error::UnexpectedError(error.to_string()))
82    }
83}
84
85/*
86#[cfg(any(feature = "fuzzing", test))]
87pub(crate) mod test_utils {
88    use crate::{
89        coordinator::StateSyncCoordinator,
90        executor_proxy::{ExecutorProxy, ExecutorProxyTrait},
91        network::StateSyncSender,
92    };
93    use diem_types::waypoint::Waypoint;
94
95    use channel::{diem_channel, message_queues::QueueStyle};
96    use diem_config::{
97        config::{NodeConfig, RoleType},
98        network_id::{NetworkId, NodeNetworkId},
99    };
100    use diem_types::transaction::{Transaction, WriteSetPayload};
101    use diem_vm::DiemVM;
102    use pos-ledger-db::DiemDB;
103    use executor::Executor;
104    use executor_test_helpers::bootstrap_genesis;
105    use futures::channel::mpsc;
106    use network::{
107        peer_manager::{ConnectionRequestSender, PeerManagerRequestSender},
108        protocols::network::NewNetworkSender,
109    };
110    use std::collections::HashMap;
111    use storage_interface::DbReaderWriter;
112
113    #[cfg(test)]
114    pub(crate) fn create_coordinator_with_config_and_waypoint(
115        node_config: NodeConfig, waypoint: Waypoint,
116    ) -> StateSyncCoordinator<ExecutorProxy> {
117        create_state_sync_coordinator_for_tests(node_config, waypoint)
118    }
119
120    pub(crate) fn create_validator_coordinator(
121    ) -> StateSyncCoordinator<ExecutorProxy> {
122        let mut node_config = NodeConfig::default();
123        node_config.base.role = RoleType::Validator;
124
125        create_state_sync_coordinator_for_tests(
126            node_config,
127            Waypoint::default(),
128        )
129    }
130
131    #[cfg(test)]
132    pub(crate) fn create_full_node_coordinator(
133    ) -> StateSyncCoordinator<ExecutorProxy> {
134        let mut node_config = NodeConfig::default();
135        node_config.base.role = RoleType::FullNode;
136
137        create_state_sync_coordinator_for_tests(
138            node_config,
139            Waypoint::default(),
140        )
141    }
142
143    fn create_state_sync_coordinator_for_tests(
144        node_config: NodeConfig, waypoint: Waypoint,
145    ) -> StateSyncCoordinator<ExecutorProxy> {
146        // Generate a genesis change set
147        let (genesis, _) =
148            vm_genesis::test_genesis_change_set_and_validators(Some(1));
149
150        // Create test diem database
151        let db_path = diem_temppath::TempPath::new();
152        db_path.create_as_dir().unwrap();
153        let (db, db_rw) =
154            DbReaderWriter::wrap(DiemDB::new_for_test(db_path.path()));
155
156        // Bootstrap the genesis transaction
157        let genesis_txn =
158            Transaction::GenesisTransaction(WriteSetPayload::Direct(genesis));
159        bootstrap_genesis::<DiemVM>(&db_rw, &genesis_txn).unwrap();
160
161        // Create executor proxy
162        let chunk_executor = Box::new(Executor::<DiemVM>::new(db_rw));
163        let executor_proxy = ExecutorProxy::new(db, chunk_executor, vec![]);
164
165        // Get initial state
166        let initial_state = executor_proxy.get_local_storage_state().unwrap();
167
168        // Setup network senders
169        let (network_reqs_tx, _network_reqs_rx) =
170            diem_channel::new(QueueStyle::FIFO, 8, None);
171        let (connection_reqs_tx, _) =
172            diem_channel::new(QueueStyle::FIFO, 8, None);
173        let network_sender = StateSyncSender::new(
174            PeerManagerRequestSender::new(network_reqs_tx),
175            ConnectionRequestSender::new(connection_reqs_tx),
176        );
177        let node_network_id = NodeNetworkId::new(NetworkId::Validator, 0);
178        let network_senders = vec![(node_network_id, network_sender)]
179            .into_iter()
180            .collect::<HashMap<_, _>>();
181
182        // Create channel senders and receivers
183        let (_coordinator_sender, coordinator_receiver) = mpsc::unbounded();
184        let (mempool_sender, _mempool_receiver) = mpsc::channel(1);
185
186        // Return the new state sync coordinator
187        StateSyncCoordinator::new(
188            coordinator_receiver,
189            mempool_sender,
190            network_senders,
191            &node_config,
192            waypoint,
193            executor_proxy,
194            initial_state,
195        )
196        .unwrap()
197    }
198}
199*/