1use anyhow::Result;
9use diem_crypto::{hash::SPARSE_MERKLE_PLACEHOLDER_HASH, HashValue};
10use diem_types::{
11 committed_block::CommittedBlock,
12 contract_event::ContractEvent,
13 epoch_change::EpochChangeProof,
14 epoch_state::EpochState,
15 ledger_info::{
16 deserialize_ledger_info_unchecked, LedgerInfoWithSignatures,
17 },
18 proof::definition::LeafCount,
19 reward_distribution_event::RewardDistributionEventV2,
20 term_state::PosState,
21 transaction::{TransactionInfo, TransactionToCommit, Version},
22};
23use serde::{Deserialize, Serialize};
24use std::sync::Arc;
25use thiserror::Error;
26
27pub mod state_view;
28
29#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
30pub struct StartupInfo {
31 #[serde(deserialize_with = "deserialize_ledger_info_unchecked")]
34 pub latest_ledger_info: LedgerInfoWithSignatures,
35 pub latest_epoch_state: Option<EpochState>,
38 pub committed_tree_state: TreeState,
39 pub synced_tree_state: Option<TreeState>,
40
41 pub committed_pos_state: PosState,
42}
43
44impl StartupInfo {
45 pub fn new(
46 latest_ledger_info: LedgerInfoWithSignatures,
47 latest_epoch_state: Option<EpochState>,
48 committed_tree_state: TreeState, synced_tree_state: Option<TreeState>,
49 committed_pos_state: PosState,
50 ) -> Self {
51 Self {
52 latest_ledger_info,
53 latest_epoch_state,
54 committed_tree_state,
55 synced_tree_state,
56 committed_pos_state,
57 }
58 }
59
60 #[cfg(any(feature = "fuzzing"))]
61 pub fn new_for_testing() -> Self {
62 use diem_types::on_chain_config::ValidatorSet;
63
64 let latest_ledger_info = LedgerInfoWithSignatures::genesis(
65 HashValue::zero(),
66 ValidatorSet::empty(),
67 );
68 let latest_epoch_state = None;
69 let committed_tree_state = TreeState {
70 num_transactions: 0,
71 ledger_frozen_subtree_hashes: Vec::new(),
72 account_state_root_hash: *SPARSE_MERKLE_PLACEHOLDER_HASH,
73 };
74 let synced_tree_state = None;
75
76 Self {
77 latest_ledger_info,
78 latest_epoch_state,
79 committed_tree_state,
80 synced_tree_state,
81 }
82 }
83
84 pub fn get_epoch_state(&self) -> &EpochState {
85 self.latest_ledger_info
86 .ledger_info()
87 .next_epoch_state()
88 .unwrap_or_else(|| {
89 self.latest_epoch_state
90 .as_ref()
91 .expect("EpochState must exist")
92 })
93 }
94}
95
96#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
97pub struct TreeState {
98 pub num_transactions: LeafCount,
99 pub ledger_frozen_subtree_hashes: Vec<HashValue>,
100 pub account_state_root_hash: HashValue,
101}
102
103impl TreeState {
104 pub fn new(
105 num_transactions: LeafCount,
106 ledger_frozen_subtree_hashes: Vec<HashValue>,
107 account_state_root_hash: HashValue,
108 ) -> Self {
109 Self {
110 num_transactions,
111 ledger_frozen_subtree_hashes,
112 account_state_root_hash,
113 }
114 }
115
116 pub fn describe(&self) -> &'static str {
117 if self.num_transactions != 0 {
118 "DB has been bootstrapped."
119 } else if self.account_state_root_hash
120 != *SPARSE_MERKLE_PLACEHOLDER_HASH
121 {
122 "DB has no transaction, but a non-empty pre-genesis state."
123 } else {
124 "DB is empty, has no transaction or state."
125 }
126 }
127}
128
129#[derive(Debug, Deserialize, Error, PartialEq, Serialize)]
130pub enum Error {
131 #[error("Service error: {:?}", error)]
132 ServiceError { error: String },
133
134 #[error("Serialization error: {0}")]
135 SerializationError(String),
136}
137
138impl From<anyhow::Error> for Error {
139 fn from(error: anyhow::Error) -> Self {
140 Self::ServiceError {
141 error: format!("{}", error),
142 }
143 }
144}
145
146impl From<bcs::Error> for Error {
147 fn from(error: bcs::Error) -> Self {
148 Self::SerializationError(format!("{}", error))
149 }
150}
151
152#[derive(Clone, Copy, Eq, PartialEq)]
153pub enum Order {
154 Ascending,
155 Descending,
156}
157
158pub trait DbReader: Send + Sync {
161 fn get_epoch_ending_ledger_infos(
166 &self, start_epoch: u64, end_epoch: u64,
167 ) -> Result<EpochChangeProof>;
168
169 fn get_block_timestamp(&self, version: u64) -> Result<u64>;
174
175 fn get_latest_ledger_info(&self) -> Result<LedgerInfoWithSignatures>;
177
178 fn get_latest_version(&self) -> Result<Version> {
180 Ok(self.get_latest_ledger_info()?.ledger_info().version())
181 }
182
183 fn get_latest_commit_metadata(&self) -> Result<(Version, u64)> {
185 let ledger_info_with_sig = self.get_latest_ledger_info()?;
186 let ledger_info = ledger_info_with_sig.ledger_info();
187 Ok((ledger_info.version(), ledger_info.timestamp_usecs()))
188 }
189
190 fn get_startup_info(
196 &self, need_pos_state: bool,
197 ) -> Result<Option<StartupInfo>>;
198
199 fn get_latest_tree_state(&self) -> Result<TreeState>;
202
203 fn get_epoch_ending_ledger_info(
205 &self, known_version: u64,
206 ) -> Result<LedgerInfoWithSignatures>;
207
208 fn get_latest_transaction_info_option(
212 &self,
213 ) -> Result<Option<(Version, TransactionInfo)>> {
214 unimplemented!()
215 }
216
217 fn get_pos_state(&self, _block_id: &HashValue) -> Result<PosState> {
218 unimplemented!()
219 }
220
221 fn get_latest_pos_state(&self) -> Arc<PosState> { unimplemented!() }
222}
223
224pub trait DbWriter: Send + Sync {
227 fn save_transactions(
234 &self, txns_to_commit: &[TransactionToCommit], first_version: Version,
235 ledger_info_with_sigs: Option<&LedgerInfoWithSignatures>,
236 pos_state: Option<PosState>, committed_blocks: Vec<CommittedBlock>,
237 ledger_infos_with_voted_block: Vec<(
238 HashValue,
239 LedgerInfoWithSignatures,
240 )>,
241 ) -> Result<()>;
242
243 fn save_reward_event(
244 &self, epoch: u64, event: &RewardDistributionEventV2,
245 ) -> Result<()>;
246
247 fn delete_pos_state_by_block(&self, block_id: &HashValue) -> Result<()>;
248}
249
250#[derive(Clone)]
251pub struct DbReaderWriter {
252 pub reader: Arc<dyn DbReader>,
253 pub writer: Arc<dyn DbWriter>,
254}
255
256impl DbReaderWriter {
257 pub fn new<D: 'static + DbReader + DbWriter>(db: D) -> Self {
258 let reader = Arc::new(db);
259 let writer = Arc::clone(&reader);
260
261 Self { reader, writer }
262 }
263
264 pub fn from_arc<D: 'static + DbReader + DbWriter>(arc_db: Arc<D>) -> Self {
265 let reader = Arc::clone(&arc_db);
266 let writer = Arc::clone(&arc_db);
267
268 Self { reader, writer }
269 }
270
271 pub fn wrap<D: 'static + DbReader + DbWriter>(db: D) -> (Arc<D>, Self) {
272 let arc_db = Arc::new(db);
273 (Arc::clone(&arc_db), Self::from_arc(arc_db))
274 }
275}
276
277impl<D> From<D> for DbReaderWriter
278where D: 'static + DbReader + DbWriter
279{
280 fn from(db: D) -> Self { Self::new(db) }
281}
282
283pub trait DBReaderForPoW: Send + Sync + DbReader {
284 fn get_latest_ledger_info_option(&self)
285 -> Option<LedgerInfoWithSignatures>;
286
287 fn get_block_ledger_info(
289 &self, consensus_block_id: &HashValue,
290 ) -> Result<LedgerInfoWithSignatures>;
291
292 fn get_events_by_version(
293 &self, start_version: u64, end_version: u64,
294 ) -> Result<Vec<ContractEvent>>;
295
296 fn get_epoch_ending_blocks(
297 &self, start_epoch: u64, end_epoch: u64,
298 ) -> Result<Vec<HashValue>>;
299
300 fn get_reward_event(&self, epoch: u64)
301 -> Result<RewardDistributionEventV2>;
302
303 fn get_committed_block_by_hash(
304 &self, block_hash: &HashValue,
305 ) -> Result<CommittedBlock>;
306
307 fn get_committed_block_hash_by_view(&self, view: u64) -> Result<HashValue>;
308
309 fn get_ledger_info_by_voted_block(
310 &self, block_id: &HashValue,
311 ) -> Result<LedgerInfoWithSignatures>;
312
313 fn get_block_hash_by_epoch_and_round(
314 &self, epoch: u64, round: u64,
315 ) -> Result<HashValue>;
316}