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*/