forked from aptos-labs/aptos-core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvm_validator.rs
126 lines (107 loc) · 3.72 KB
/
vm_validator.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0
use anyhow::Result;
use aptos_state_view::StateViewId;
use aptos_types::{
account_address::AccountAddress,
account_config::{AccountResource, AccountSequenceInfo},
account_state::AccountState,
on_chain_config::OnChainConfigPayload,
transaction::{SignedTransaction, VMValidatorResult},
};
use aptos_vm::AptosVM;
use executor::components::apply_chunk_output::IntoLedgerView;
use fail::fail_point;
use std::{convert::TryFrom, sync::Arc};
use storage_interface::{state_view::VerifiedStateView, DbReader};
#[cfg(test)]
#[path = "unit_tests/vm_validator_test.rs"]
mod vm_validator_test;
pub trait TransactionValidation: Send + Sync + Clone {
type ValidationInstance: aptos_vm::VMValidator;
/// Validate a txn from client
fn validate_transaction(&self, _txn: SignedTransaction) -> Result<VMValidatorResult>;
/// Restart the transaction validation instance
fn restart(&mut self, config: OnChainConfigPayload) -> Result<()>;
/// Notify about new commit
fn notify_commit(&mut self);
}
fn latest_state_view(db_reader: &Arc<dyn DbReader>) -> VerifiedStateView {
let ledger_view = db_reader
.get_latest_tree_state()
.expect("Should not fail.")
.into_ledger_view(db_reader)
.expect("Should not fail.");
ledger_view.state_view(
&ledger_view,
StateViewId::TransactionValidation {
base_version: ledger_view.version().expect("Must be bootstrapped."),
},
db_reader.clone(),
)
}
pub struct VMValidator {
db_reader: Arc<dyn DbReader>,
cached_state_view: VerifiedStateView,
vm: AptosVM,
}
impl Clone for VMValidator {
fn clone(&self) -> Self {
Self::new(self.db_reader.clone())
}
}
impl VMValidator {
pub fn new(db_reader: Arc<dyn DbReader>) -> Self {
let cached_state_view = latest_state_view(&db_reader);
let vm = AptosVM::new_for_validation(&cached_state_view);
VMValidator {
db_reader,
cached_state_view,
vm,
}
}
}
impl TransactionValidation for VMValidator {
type ValidationInstance = AptosVM;
fn validate_transaction(&self, txn: SignedTransaction) -> Result<VMValidatorResult> {
fail_point!("vm_validator::validate_transaction", |_| {
Err(anyhow::anyhow!(
"Injected error in vm_validator::validate_transaction"
))
});
use aptos_vm::VMValidator;
Ok(self.vm.validate_transaction(txn, &self.cached_state_view))
}
fn restart(&mut self, _config: OnChainConfigPayload) -> Result<()> {
self.notify_commit();
self.vm = AptosVM::new_for_validation(&self.cached_state_view);
Ok(())
}
fn notify_commit(&mut self) {
self.cached_state_view = latest_state_view(&self.db_reader);
}
}
/// returns account's sequence number from storage
pub fn get_account_sequence_number(
storage: &dyn DbReader,
address: AccountAddress,
) -> Result<AccountSequenceInfo> {
fail_point!("vm_validator::get_account_sequence_number", |_| {
Err(anyhow::anyhow!(
"Injected error in get_account_sequence_number"
))
});
match storage.get_latest_account_state(address)? {
Some(blob) => {
if let Ok(Some(crsn)) = AccountState::try_from(&blob)?.get_crsn_resource() {
return Ok(AccountSequenceInfo::CRSN {
min_nonce: crsn.min_nonce(),
size: crsn.size(),
});
}
let seqno = AccountResource::try_from(&blob)?.sequence_number();
Ok(AccountSequenceInfo::Sequential(seqno))
}
None => Ok(AccountSequenceInfo::Sequential(0)),
}
}