-
Notifications
You must be signed in to change notification settings - Fork 687
/
Copy pathcold_storage.rs
140 lines (121 loc) · 4.93 KB
/
cold_storage.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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
use crate::tests::client::process_blocks::create_nightshade_runtimes;
use near_chain::{ChainGenesis, Provenance};
use near_chain_configs::Genesis;
use near_client::test_utils::TestEnv;
use near_crypto::{InMemorySigner, KeyType};
use near_o11y::testonly::init_test_logger;
use near_primitives::transaction::{
Action, DeployContractAction, FunctionCallAction, SignedTransaction,
};
use near_store::cold_storage::{test_cold_genesis_update, test_get_store_reads, update_cold_db};
use near_store::db::TestDB;
use near_store::{DBCol, NodeStorage, Store, Temperature};
use nearcore::config::GenesisExt;
use strum::IntoEnumIterator;
fn check_key(first_store: &Store, second_store: &Store, col: DBCol, key: &[u8]) {
tracing::debug!("Checking {:?} {:?}", col, key);
let first_res = first_store.get(col, key);
let second_res = second_store.get(col, key);
assert_eq!(first_res.unwrap(), second_res.unwrap());
}
fn check_iter(first_store: &Store, second_store: &Store, col: DBCol) -> u64 {
let mut num_checks = 0;
for (key, _) in first_store.iter(col).map(Result::unwrap) {
check_key(first_store, second_store, col, &key);
num_checks += 1;
}
num_checks
}
/// Deploying test contract and calling write_random_value 5 times every block for 4 epochs.
/// Also doing 5 send transactions every block.
/// 4 epochs, because this test does not cover gc behaviour.
/// After every block updating a separate database with data from client's storage.
/// After 4 epochs we check that everything, that exists in cold columns
/// of the storage of the client also exists in the database to which we were writing.
#[test]
fn test_storage_after_commit_of_cold_update() {
init_test_logger();
let cold_db = TestDB::new();
let epoch_length = 5;
let max_height = epoch_length * 4;
let mut genesis = Genesis::test(vec!["test0".parse().unwrap(), "test1".parse().unwrap()], 1);
genesis.config.epoch_length = epoch_length;
let mut chain_genesis = ChainGenesis::test();
chain_genesis.epoch_length = epoch_length;
let mut env = TestEnv::builder(chain_genesis)
.runtime_adapters(create_nightshade_runtimes(&genesis, 1))
.build();
let mut last_hash = *env.clients[0].chain.genesis().hash();
test_cold_genesis_update(&*cold_db, &env.clients[0].runtime_adapter.store()).unwrap();
let state_reads = test_get_store_reads(DBCol::State);
for h in 1..max_height {
let signer = InMemorySigner::from_seed("test0".parse().unwrap(), KeyType::ED25519, "test0");
if h == 1 {
let tx = SignedTransaction::from_actions(
h,
"test0".parse().unwrap(),
"test0".parse().unwrap(),
&signer,
vec![Action::DeployContract(DeployContractAction {
code: near_test_contracts::rs_contract().to_vec(),
})],
last_hash,
);
env.clients[0].process_tx(tx, false, false);
}
for i in 0..5 {
let tx = SignedTransaction::from_actions(
h * 10 + i,
"test0".parse().unwrap(),
"test0".parse().unwrap(),
&signer,
vec![Action::FunctionCall(FunctionCallAction {
method_name: "write_random_value".to_string(),
args: vec![],
gas: 100_000_000_000_000,
deposit: 0,
})],
last_hash,
);
env.clients[0].process_tx(tx, false, false);
}
for i in 0..5 {
let tx = SignedTransaction::send_money(
h * 10 + i,
"test0".parse().unwrap(),
"test0".parse().unwrap(),
&signer,
1,
last_hash,
);
env.clients[0].process_tx(tx, false, false);
}
let block = env.clients[0].produce_block(h).unwrap().unwrap();
env.process_block(0, block.clone(), Provenance::PRODUCED);
update_cold_db(
&*cold_db,
&env.clients[0].runtime_adapter.store(),
&env.clients[0]
.runtime_adapter
.get_shard_layout(
&env.clients[0]
.runtime_adapter
.get_epoch_id_from_prev_block(&last_hash)
.unwrap(),
)
.unwrap(),
&h,
)
.unwrap();
last_hash = block.hash().clone();
}
// assert that we don't read State from db, but from TrieChanges
assert_eq!(state_reads, test_get_store_reads(DBCol::State));
let cold_store = NodeStorage::new(cold_db).get_store(Temperature::Hot);
for col in DBCol::iter() {
if col.is_cold() {
// assert that this test actually checks something
assert!(check_iter(&env.clients[0].runtime_adapter.store(), &cold_store, col) > 0);
}
}
}