1#![forbid(unsafe_code)]
9
10use std::{cmp::max, collections::HashMap, sync::Arc};
11
12use anyhow::Result;
13use serde::{Deserialize, Serialize};
14
15use diem_crypto::{
16 hash::{TransactionAccumulatorHasher, SPARSE_MERKLE_PLACEHOLDER_HASH},
17 HashValue,
18};
19use diem_types::{
20 account_state_blob::AccountStateBlob,
21 block_info::PivotBlockDecision,
22 contract_event::ContractEvent,
23 epoch_state::EpochState,
24 ledger_info::LedgerInfoWithSignatures,
25 proof::{accumulator::InMemoryAccumulator, AccumulatorExtensionProof},
26 term_state::PosState,
27 transaction::{
28 Transaction, TransactionInfo, TransactionListWithProof,
29 TransactionStatus, Version,
30 },
31 validator_config::ConsensusSignature,
32};
33pub use error::Error;
34use scratchpad::ProofRead;
35use storage_interface::TreeState;
36
37pub use self::processed_vm_output::{ProcessedVMOutput, TransactionData};
38
39mod error;
40mod processed_vm_output;
41
42type SparseMerkleProof = diem_types::proof::SparseMerkleProof<AccountStateBlob>;
43type SparseMerkleTree = scratchpad::SparseMerkleTree<AccountStateBlob>;
44
45pub trait ChunkExecutor: Send {
46 fn execute_and_commit_chunk(
51 &self,
52 txn_list_with_proof: TransactionListWithProof,
53 verified_target_li: LedgerInfoWithSignatures,
56 epoch_change_li: Option<LedgerInfoWithSignatures>,
59 ) -> Result<Vec<ContractEvent>>;
60}
61
62pub trait BlockExecutor: Send {
63 fn committed_block_id(&self) -> Result<HashValue, Error>;
65
66 fn execute_block(
68 &self, block: (HashValue, Vec<Transaction>),
69 parent_block_id: HashValue, catch_up_mode: bool,
70 ) -> Result<StateComputeResult, Error>;
71
72 fn commit_blocks(
87 &self, block_ids: Vec<HashValue>,
88 ledger_info_with_sigs: LedgerInfoWithSignatures,
89 ) -> Result<(Vec<Transaction>, Vec<ContractEvent>), Error>;
90}
91
92pub trait TransactionReplayer: Send {
93 fn replay_chunk(
94 &self, first_version: Version, txns: Vec<Transaction>,
95 txn_infos: Vec<TransactionInfo>,
96 ) -> Result<()>;
97
98 fn expecting_version(&self) -> Version;
99}
100
101#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
111pub struct StateComputeResult {
112 root_hash: HashValue,
115 frozen_subtree_roots: Vec<HashValue>,
118
119 parent_frozen_subtree_roots: Vec<HashValue>,
121
122 num_leaves: u64,
126
127 parent_num_leaves: u64,
129
130 epoch_state: Option<EpochState>,
133 compute_status: Vec<TransactionStatus>,
137
138 transaction_info_hashes: Vec<HashValue>,
140
141 signature: Option<ConsensusSignature>,
143
144 pivot_decision: Option<PivotBlockDecision>,
146}
147
148impl StateComputeResult {
149 pub fn new(
150 root_hash: HashValue, frozen_subtree_roots: Vec<HashValue>,
151 num_leaves: u64, parent_frozen_subtree_roots: Vec<HashValue>,
152 parent_num_leaves: u64, epoch_state: Option<EpochState>,
153 compute_status: Vec<TransactionStatus>,
154 transaction_info_hashes: Vec<HashValue>,
155 pivot_decision: Option<PivotBlockDecision>,
156 ) -> Self {
157 Self {
158 root_hash,
159 frozen_subtree_roots,
160 num_leaves,
161 parent_frozen_subtree_roots,
162 parent_num_leaves,
163 epoch_state,
164 compute_status,
165 transaction_info_hashes,
166 signature: None,
167 pivot_decision,
168 }
169 }
170}
171
172impl StateComputeResult {
173 pub fn version(&self) -> Version {
174 max(self.num_leaves, 1)
175 .checked_sub(1)
176 .expect("Integer overflow occurred")
177 }
178
179 pub fn root_hash(&self) -> HashValue { self.root_hash }
180
181 pub fn compute_status(&self) -> &Vec<TransactionStatus> {
182 &self.compute_status
183 }
184
185 pub fn epoch_state(&self) -> &Option<EpochState> { &self.epoch_state }
186
187 pub fn extension_proof(
188 &self,
189 ) -> AccumulatorExtensionProof<TransactionAccumulatorHasher> {
190 AccumulatorExtensionProof::<TransactionAccumulatorHasher>::new(
191 self.parent_frozen_subtree_roots.clone(),
192 self.parent_num_leaves(),
193 self.transaction_info_hashes().clone(),
194 )
195 }
196
197 pub fn transaction_info_hashes(&self) -> &Vec<HashValue> {
198 &self.transaction_info_hashes
199 }
200
201 pub fn num_leaves(&self) -> u64 { self.num_leaves }
202
203 pub fn frozen_subtree_roots(&self) -> &Vec<HashValue> {
204 &self.frozen_subtree_roots
205 }
206
207 pub fn parent_num_leaves(&self) -> u64 { self.parent_num_leaves }
208
209 pub fn parent_frozen_subtree_roots(&self) -> &Vec<HashValue> {
210 &self.parent_frozen_subtree_roots
211 }
212
213 pub fn pivot_decision(&self) -> &Option<PivotBlockDecision> {
214 &self.pivot_decision
215 }
216
217 pub fn has_reconfiguration(&self) -> bool { self.epoch_state.is_some() }
218
219 pub fn signature(&self) -> &Option<ConsensusSignature> { &self.signature }
220
221 pub fn set_signature(&mut self, sig: ConsensusSignature) {
222 self.signature = Some(sig);
223 }
224}
225
226#[derive(Clone, Debug)]
230pub struct ExecutedTrees {
231 state_tree: Arc<SparseMerkleTree>,
236
237 transaction_accumulator:
240 Arc<InMemoryAccumulator<TransactionAccumulatorHasher>>,
241
242 pos_state: PosState,
243}
244
245impl From<TreeState> for ExecutedTrees {
246 fn from(tree_state: TreeState) -> Self {
247 ExecutedTrees::new(
248 tree_state.account_state_root_hash,
249 tree_state.ledger_frozen_subtree_hashes,
250 tree_state.num_transactions,
251 PosState::new_empty(),
253 )
254 }
255}
256
257impl ExecutedTrees {
258 pub fn new_with_pos_state(
259 tree_state: TreeState, pos_state: PosState,
260 ) -> Self {
261 ExecutedTrees::new(
262 tree_state.account_state_root_hash,
263 tree_state.ledger_frozen_subtree_hashes,
264 tree_state.num_transactions,
265 pos_state,
266 )
267 }
268
269 pub fn new_copy(
270 state_tree: Arc<SparseMerkleTree>,
271 transaction_accumulator: Arc<
272 InMemoryAccumulator<TransactionAccumulatorHasher>,
273 >,
274 pos_state: PosState,
275 ) -> Self {
276 Self {
277 state_tree,
278 transaction_accumulator,
279 pos_state,
280 }
281 }
282
283 pub fn state_tree(&self) -> &Arc<SparseMerkleTree> { &self.state_tree }
284
285 pub fn pos_state(&self) -> &PosState { &self.pos_state }
286
287 pub fn txn_accumulator(
288 &self,
289 ) -> &Arc<InMemoryAccumulator<TransactionAccumulatorHasher>> {
290 &self.transaction_accumulator
291 }
292
293 pub fn version(&self) -> Option<Version> {
294 let num_elements = self.txn_accumulator().num_leaves() as u64;
295 num_elements.checked_sub(1)
296 }
297
298 pub fn state_id(&self) -> HashValue { self.txn_accumulator().root_hash() }
299
300 pub fn state_root(&self) -> HashValue { self.state_tree().root_hash() }
301
302 pub fn new(
303 state_root_hash: HashValue,
304 frozen_subtrees_in_accumulator: Vec<HashValue>,
305 num_leaves_in_accumulator: u64, pos_state: PosState,
306 ) -> ExecutedTrees {
307 ExecutedTrees {
308 state_tree: Arc::new(SparseMerkleTree::new(state_root_hash)),
309 transaction_accumulator: Arc::new(
310 InMemoryAccumulator::new(
311 frozen_subtrees_in_accumulator,
312 num_leaves_in_accumulator,
313 )
314 .expect("The startup info read from storage should be valid."),
315 ),
316 pos_state,
317 }
318 }
319
320 pub fn new_empty() -> ExecutedTrees {
321 Self::new(
322 *SPARSE_MERKLE_PLACEHOLDER_HASH,
323 vec![],
324 0,
325 PosState::new_empty(),
326 )
327 }
328
329 pub fn set_pos_state_skipped(&mut self, skipped: bool) {
330 self.pos_state.set_skipped(skipped)
331 }
332}
333
334pub struct ProofReader {
335 account_to_proof: HashMap<HashValue, SparseMerkleProof>,
336}
337
338impl ProofReader {
339 pub fn new(
340 account_to_proof: HashMap<HashValue, SparseMerkleProof>,
341 ) -> Self {
342 ProofReader { account_to_proof }
343 }
344}
345
346impl ProofRead<AccountStateBlob> for ProofReader {
347 fn get_proof(&self, key: HashValue) -> Option<&SparseMerkleProof> {
348 self.account_to_proof.get(&key)
349 }
350}