1#![doc(html_favicon_url = "https://dev.namada.net/master/favicon.png")]
4#![doc(html_logo_url = "https://dev.namada.net/master/rustdoc-logo.png")]
5#![deny(rustdoc::broken_intra_doc_links)]
6#![deny(rustdoc::private_intra_doc_links)]
7#![warn(
8 missing_docs,
9 rust_2018_idioms,
10 clippy::cast_sign_loss,
11 clippy::cast_possible_truncation,
12 clippy::cast_possible_wrap,
13 clippy::cast_lossless,
14 clippy::arithmetic_side_effects,
15 clippy::dbg_macro,
16 clippy::print_stdout,
17 clippy::print_stderr
18)]
19
20mod in_memory;
21pub mod prefix_iter;
22mod wl_state;
23pub mod write_log;
24
25use std::fmt::Debug;
26use std::iter::Peekable;
27
28pub use in_memory::{
29 BlockStorage, InMemory, LastBlock, ProcessProposalCachedResult,
30};
31use namada_core::address::Address;
32use namada_core::arith::checked;
33use namada_core::chain::ChainId;
34pub use namada_core::chain::{
35 BLOCK_HASH_LENGTH, BLOCK_HEIGHT_LENGTH, BlockHash, BlockHeader,
36 BlockHeight, Epoch, Epochs,
37};
38use namada_core::eth_bridge_pool::is_pending_transfer_key;
39use namada_core::hash::Hash;
40pub use namada_core::hash::Sha256Hasher;
41pub use namada_core::storage::{
42 BlockResults, EPOCH_TYPE_LENGTH, EthEventsQueue, Key, KeySeg, TxIndex,
43};
44use namada_core::tendermint::merkle::proof::ProofOps;
45use namada_gas::{
46 Gas, MEMORY_ACCESS_GAS_PER_BYTE, STORAGE_ACCESS_GAS_PER_BYTE,
47};
48use namada_merkle_tree::Error as MerkleTreeError;
49pub use namada_merkle_tree::{
50 self as merkle_tree, MembershipProof, MerkleTree, MerkleTreeStoresRead,
51 MerkleTreeStoresWrite, StoreRef, StoreType, ics23_specs,
52};
53pub use namada_storage as storage;
54pub use namada_storage::conversion_state::{
55 ConversionLeaf, ConversionState, ReadConversionState, WithConversionState,
56};
57pub use namada_storage::types::{KVBytes, PatternIterator, PrefixIterator};
58pub use namada_storage::{
59 BlockStateRead, BlockStateWrite, DB, DBIter, DBWriteBatch, DbError,
60 DbResult, Error, OptionExt, Result, ResultExt, StorageHasher, StorageRead,
61 StorageWrite, collections, iter_prefix, iter_prefix_bytes,
62 iter_prefix_with_filter, iter_prefix_with_filter_map, mockdb, tx_queue,
63};
64use namada_systems::parameters;
65use thiserror::Error;
66use wl_state::TxWlState;
67pub use wl_state::{FullAccessState, TempWlState, WlState};
68use write_log::WriteLog;
69
70pub const EPOCH_SWITCH_BLOCKS_DELAY: u32 = 2;
73
74pub trait StateRead: StorageRead + Debug {
76 type D: 'static + DB + for<'iter> DBIter<'iter>;
78 type H: 'static + StorageHasher;
80
81 fn write_log(&self) -> &WriteLog;
83
84 fn db(&self) -> &Self::D;
86
87 fn in_mem(&self) -> &InMemory<Self::H>;
89
90 fn charge_gas(&self, gas: Gas) -> Result<()>;
92
93 fn db_has_key(&self, key: &storage::Key) -> Result<(bool, Gas)> {
96 let len = key.len() as u64;
97 Ok((
98 self.db().read_subspace_val(key)?.is_some(),
99 checked!(len * STORAGE_ACCESS_GAS_PER_BYTE)?.into(),
100 ))
101 }
102
103 fn db_read(&self, key: &storage::Key) -> Result<(Option<Vec<u8>>, Gas)> {
105 tracing::trace!("storage read key {}", key);
106
107 match self.db().read_subspace_val(key)? {
108 Some(v) => {
109 let len = checked!(key.len() + v.len())? as u64;
110 let gas = checked!(len * STORAGE_ACCESS_GAS_PER_BYTE)?;
111 Ok((Some(v), gas.into()))
112 }
113 None => {
114 let len = key.len() as u64;
115 let gas = checked!(len * STORAGE_ACCESS_GAS_PER_BYTE)?;
116 Ok((None, gas.into()))
117 }
118 }
119 }
120
121 fn db_iter_prefix(
127 &self,
128 prefix: &Key,
129 ) -> Result<(<Self::D as DBIter<'_>>::PrefixIter, Gas)> {
130 let len = prefix.len() as u64;
131 Ok((
132 self.db().iter_prefix(Some(prefix)),
133 checked!(len * STORAGE_ACCESS_GAS_PER_BYTE)?.into(),
134 ))
135 }
136
137 fn db_iter_results(&self) -> (<Self::D as DBIter<'_>>::PrefixIter, Gas) {
139 (self.db().iter_results(), Gas::default())
140 }
141
142 fn validity_predicate<Params: parameters::Keys>(
145 &self,
146 addr: &Address,
147 ) -> Result<(Option<Hash>, Gas)> {
148 let key = if let Address::Implicit(_) = addr {
149 Params::implicit_vp_key()
150 } else {
151 Key::validity_predicate(addr)
152 };
153 match self.db_read(&key)? {
154 (Some(value), gas) => {
155 let vp_code_hash = Hash::try_from(&value[..])?;
156 Ok((Some(vp_code_hash), gas))
157 }
158 (None, gas) => Ok((None, gas)),
159 }
160 }
161
162 fn get_block_header(
164 &self,
165 height: Option<BlockHeight>,
166 ) -> Result<(Option<BlockHeader>, Gas)> {
167 match height {
168 Some(h) if h == self.in_mem().get_block_height().0 => {
169 let header = self.in_mem().header.clone();
170 let gas = if header.is_some() {
171 let len = BlockHeader::encoded_len() as u64;
172 checked!(len * MEMORY_ACCESS_GAS_PER_BYTE)?
173 } else {
174 MEMORY_ACCESS_GAS_PER_BYTE
175 };
176 Ok((header, gas.into()))
177 }
178 Some(h) => match self.db().read_block_header(h)? {
179 Some(header) => {
180 let len = BlockHeader::encoded_len() as u64;
181 let gas = checked!(len * STORAGE_ACCESS_GAS_PER_BYTE)?;
182 Ok((Some(header), gas.into()))
183 }
184 None => Ok((None, STORAGE_ACCESS_GAS_PER_BYTE.into())),
185 },
186 None => Ok((
187 self.in_mem().header.clone(),
188 STORAGE_ACCESS_GAS_PER_BYTE.into(),
189 )),
190 }
191 }
192}
193
194pub trait State: StateRead + StorageWrite {
196 fn write_log_mut(&mut self) -> &mut WriteLog;
198
199 fn split_borrow(&mut self)
203 -> (&mut WriteLog, &InMemory<Self::H>, &Self::D);
204
205 fn write_tx_hash(&mut self, hash: Hash) -> write_log::Result<()> {
207 self.write_log_mut().write_tx_hash(hash)
208 }
209}
210
211pub trait TxWrites: StateRead {
213 fn with_tx_writes(&mut self) -> TxWlState<'_, Self::D, Self::H>;
215}
216
217#[macro_export]
220macro_rules! impl_storage_read {
221 ($($type:ty)*) => {
222 impl<D, H> StorageRead for $($type)*
223 where
224 D: 'static + DB + for<'iter> DBIter<'iter>,
225 H: 'static + StorageHasher,
226 {
227 type PrefixIter<'iter> = PrefixIter<'iter, D> where Self: 'iter;
228
229 fn read_bytes(
230 &self,
231 key: &storage::Key,
232 ) -> namada_storage::Result<Option<Vec<u8>>> {
233 let (log_val, gas) = self.write_log().read(key)?;
235 self.charge_gas(gas).into_storage_result()?;
236 match &log_val {
237 Some(write_log::StorageModification::Write { value }) => {
238 Ok(Some(value.clone()))
239 }
240 Some(write_log::StorageModification::Delete) => Ok(None),
241 Some(write_log::StorageModification::InitAccount {
242 vp_code_hash,
243 }) => Ok(Some(vp_code_hash.to_vec())),
244 None => {
245 let (value, gas) = self.db_read(key).into_storage_result()?;
247 self.charge_gas(gas).into_storage_result()?;
248 Ok(value)
249 }
250 }
251 }
252
253 fn has_key(&self, key: &storage::Key) -> namada_storage::Result<bool> {
254 let (log_val, gas) = self.write_log().read(key)?;
256 self.charge_gas(gas).into_storage_result()?;
257 match log_val {
258 Some(&write_log::StorageModification::Write { .. })
259 | Some(&write_log::StorageModification::InitAccount { .. }) => Ok(true),
260 Some(&write_log::StorageModification::Delete) => {
261 Ok(false)
263 }
264 None => {
265 let (present, gas) = self.db_has_key(key).into_storage_result()?;
267 self.charge_gas(gas).into_storage_result()?;
268 Ok(present)
269 }
270 }
271 }
272
273 fn iter_prefix<'iter>(
274 &'iter self,
275 prefix: &storage::Key,
276 ) -> namada_storage::Result<Self::PrefixIter<'iter>> {
277 let (iter, gas) =
278 iter_prefix_post(self.write_log(), self.db(), prefix)?;
279 self.charge_gas(gas).into_storage_result()?;
280 Ok(iter)
281 }
282
283 fn iter_next<'iter>(
284 &'iter self,
285 iter: &mut Self::PrefixIter<'iter>,
286 ) -> namada_storage::Result<Option<(String, Vec<u8>)>> {
287 iter.next().map(|(key, val, gas)| {
288 self.charge_gas(gas).into_storage_result()?;
289 Ok((key, val))
290 }).transpose()
291 }
292
293 fn get_chain_id(
294 &self,
295 ) -> std::result::Result<ChainId, namada_storage::Error> {
296 let (chain_id, gas) = self.in_mem().get_chain_id();
297 self.charge_gas(gas).into_storage_result()?;
298 Ok(chain_id)
299 }
300
301 fn get_block_height(
302 &self,
303 ) -> std::result::Result<BlockHeight, namada_storage::Error> {
304 let (height, gas) = self.in_mem().get_block_height();
305 self.charge_gas(gas).into_storage_result()?;
306 Ok(height)
307 }
308
309 fn get_block_header(
310 &self,
311 height: BlockHeight,
312 ) -> std::result::Result<Option<BlockHeader>, namada_storage::Error>
313 {
314 let (header, gas) =
315 StateRead::get_block_header(self, Some(height)).into_storage_result()?;
316 self.charge_gas(gas).into_storage_result()?;
317 Ok(header)
318 }
319
320 fn get_block_epoch(
321 &self,
322 ) -> std::result::Result<Epoch, namada_storage::Error> {
323 let (epoch, gas) = self.in_mem().get_current_epoch();
324 self.charge_gas(gas).into_storage_result()?;
325 Ok(epoch)
326 }
327
328 fn get_pred_epochs(&self) -> namada_storage::Result<Epochs> {
329 self.charge_gas(
330 namada_gas::STORAGE_ACCESS_GAS_PER_BYTE.into(),
331 ).into_storage_result()?;
332 Ok(self.in_mem().block.pred_epochs.clone())
333 }
334
335 fn get_tx_index(
336 &self,
337 ) -> std::result::Result<storage::TxIndex, namada_storage::Error> {
338 self.charge_gas(
339 namada_gas::STORAGE_ACCESS_GAS_PER_BYTE.into(),
340 ).into_storage_result()?;
341 Ok(self.in_mem().tx_index)
342 }
343
344 fn get_native_token(&self) -> namada_storage::Result<Address> {
345 self.charge_gas(
346 namada_gas::STORAGE_ACCESS_GAS_PER_BYTE.into(),
347 ).into_storage_result()?;
348 Ok(self.in_mem().native_token.clone())
349 }
350 }
351 }
352}
353
354#[macro_export]
356macro_rules! impl_storage_write {
357 ($($type:ty)*) => {
358 impl<D, H> StorageWrite for $($type)*
359 where
360 D: 'static + DB + for<'iter> DBIter<'iter>,
361 H: 'static + StorageHasher,
362 {
363 fn write_bytes(
364 &mut self,
365 key: &storage::Key,
366 val: impl AsRef<[u8]>,
367 ) -> namada_storage::Result<()> {
368 let (gas, _size_diff) = self
369 .write_log_mut()
370 .write(key, val.as_ref().to_vec())
371 .into_storage_result()?;
372 self.charge_gas(gas).into_storage_result()?;
373 Ok(())
374 }
375
376 fn delete(&mut self, key: &storage::Key) -> namada_storage::Result<()> {
377 let (gas, _size_diff) = self
378 .write_log_mut()
379 .delete(key)
380 .into_storage_result()?;
381 self.charge_gas(gas).into_storage_result()?;
382 Ok(())
383 }
384 }
385 };
386}
387
388macro_rules! impl_storage_write_by_protocol {
391 ($($type:ty)*) => {
392 impl<D, H> StorageWrite for $($type)*
393 where
394 D: 'static + DB + for<'iter> DBIter<'iter>,
395 H: 'static + StorageHasher,
396 {
397 fn write_bytes(
398 &mut self,
399 key: &storage::Key,
400 val: impl AsRef<[u8]>,
401 ) -> namada_storage::Result<()> {
402 self
403 .write_log_mut()
404 .protocol_write(key, val.as_ref().to_vec())
405 .into_storage_result()?;
406 Ok(())
407 }
408
409 fn delete(&mut self, key: &storage::Key) -> namada_storage::Result<()> {
410 self
411 .write_log_mut()
412 .protocol_delete(key)
413 .into_storage_result()?;
414 Ok(())
415 }
416 }
417 };
418}
419
420impl_storage_read!(FullAccessState<D, H>);
421impl_storage_read!(WlState<D, H>);
422impl_storage_read!(TempWlState<'_, D, H>);
423impl_storage_read!(TxWlState<'_, D, H>);
424impl_storage_write_by_protocol!(FullAccessState<D, H>);
425impl_storage_write_by_protocol!(WlState<D, H>);
426impl_storage_write_by_protocol!(TempWlState<'_, D, H>);
427impl_storage_write!(TxWlState<'_, D, H>);
428
429#[allow(missing_docs)]
430#[derive(Error, Debug)]
431pub enum StateError {
432 #[error("Merkle tree at the height {height} is not stored")]
433 NoMerkleTree { height: BlockHeight },
434 #[error("{0}")]
435 Gas(namada_gas::Error),
436}
437
438impl From<StateError> for Error {
439 fn from(value: StateError) -> Self {
440 Error::new(value)
441 }
442}
443
444#[derive(Debug)]
446pub struct PrefixIter<'iter, D>
447where
448 D: DB + DBIter<'iter>,
449{
450 pub storage_iter: Peekable<<D as DBIter<'iter>>::PrefixIter>,
452 pub write_log_iter: Peekable<write_log::PrefixIter>,
454}
455
456pub fn iter_prefix_pre<'a, D>(
459 write_log: &'a WriteLog,
463 db: &'a D,
464 prefix: &storage::Key,
465) -> namada_storage::Result<(PrefixIter<'a, D>, Gas)>
466where
467 D: DB + for<'iter> DBIter<'iter>,
468{
469 let storage_iter = db.iter_prefix(Some(prefix)).peekable();
470 let write_log_iter = write_log.iter_prefix_pre(prefix).peekable();
471 let len = prefix.len() as u64;
472 Ok((
473 PrefixIter::<D> {
474 storage_iter,
475 write_log_iter,
476 },
477 checked!(len * STORAGE_ACCESS_GAS_PER_BYTE)?.into(),
478 ))
479}
480
481pub fn iter_prefix_post<'a, D>(
484 write_log: &'a WriteLog,
488 db: &'a D,
489 prefix: &storage::Key,
490) -> namada_storage::Result<(PrefixIter<'a, D>, Gas)>
491where
492 D: DB + for<'iter> DBIter<'iter>,
493{
494 let storage_iter = db.iter_prefix(Some(prefix)).peekable();
495 let write_log_iter = write_log.iter_prefix_post(prefix).peekable();
496 let len = prefix.len() as u64;
497 Ok((
498 PrefixIter::<D> {
499 storage_iter,
500 write_log_iter,
501 },
502 checked!(len * STORAGE_ACCESS_GAS_PER_BYTE)?.into(),
503 ))
504}
505
506impl<'iter, D> Iterator for PrefixIter<'iter, D>
507where
508 D: DB + DBIter<'iter>,
509{
510 type Item = (String, Vec<u8>, Gas);
511
512 fn next(&mut self) -> Option<Self::Item> {
513 enum Next {
514 ReturnWl { advance_storage: bool },
515 ReturnStorage,
516 }
517 loop {
518 let what: Next;
519 {
520 let storage_peeked = self.storage_iter.peek();
521 let wl_peeked = self.write_log_iter.peek();
522 match (storage_peeked, wl_peeked) {
523 (None, None) => return None,
524 (None, Some(_)) => {
525 what = Next::ReturnWl {
526 advance_storage: false,
527 };
528 }
529 (Some(_), None) => {
530 what = Next::ReturnStorage;
531 }
532 (Some((storage_key, _, _)), Some((wl_key, _))) => {
533 if wl_key <= storage_key {
534 what = Next::ReturnWl {
535 advance_storage: wl_key == storage_key,
536 };
537 } else {
538 what = Next::ReturnStorage;
539 }
540 }
541 }
542 }
543 match what {
544 Next::ReturnWl { advance_storage } => {
545 if advance_storage {
546 let _ = self.storage_iter.next();
547 }
548
549 if let Some((key, modification)) =
550 self.write_log_iter.next()
551 {
552 match modification {
553 write_log::StorageModification::Write { value } => {
554 let gas = value.len() as u64;
555 return Some((key, value, gas.into()));
556 }
557 write_log::StorageModification::InitAccount {
558 vp_code_hash,
559 } => {
560 let gas = vp_code_hash.len() as u64;
561 return Some((
562 key,
563 vp_code_hash.to_vec(),
564 gas.into(),
565 ));
566 }
567 write_log::StorageModification::Delete => {
568 continue;
569 }
570 }
571 }
572 }
573 Next::ReturnStorage => {
574 if let Some(next) = self.storage_iter.next() {
575 return Some(next);
576 }
577 }
578 }
579 }
580 }
581}
582
583#[cfg(any(test, feature = "testing"))]
585pub mod testing {
586
587 use std::num::NonZeroUsize;
588
589 use clru::CLruCache;
590 use namada_core::address;
591 use namada_core::address::EstablishedAddressGen;
592 use namada_core::time::DateTimeUtc;
593 pub use namada_storage::testing::{PrefixIter, *};
594 use namada_storage::tx_queue::ExpiredTxsQueue;
595 use storage::types::CommitOnlyData;
596
597 use super::mockdb::MockDB;
598 use super::*;
599
600 pub type TestState = FullAccessState<MockDB, Sha256Hasher>;
602
603 impl Default for TestState {
604 fn default() -> Self {
605 Self(WlState {
606 write_log: Default::default(),
607 db: MockDB::default(),
608 in_mem: Default::default(),
609 diff_key_filter: diff_all_keys,
610 })
611 }
612 }
613
614 fn diff_all_keys(_key: &storage::Key) -> bool {
615 true
616 }
617
618 pub type InMemoryState = InMemory<Sha256Hasher>;
620
621 impl Default for InMemoryState {
622 fn default() -> Self {
623 let chain_id = ChainId::default();
624 let tree = MerkleTree::default();
625 let block = BlockStorage {
626 tree,
627 height: BlockHeight::default(),
628 epoch: Epoch::default(),
629 pred_epochs: Epochs::default(),
630 results: BlockResults::default(),
631 };
632 Self {
633 chain_id,
634 block,
635 header: None,
636 last_block: None,
637 last_epoch: Epoch::default(),
638 next_epoch_min_start_height: BlockHeight::default(),
639 #[allow(clippy::disallowed_methods)]
640 next_epoch_min_start_time: DateTimeUtc::now(),
641 address_gen: EstablishedAddressGen::new(
642 "Test address generator seed",
643 ),
644 update_epoch_blocks_delay: None,
645 tx_index: TxIndex::default(),
646 conversion_state: ConversionState::default(),
647 expired_txs_queue: ExpiredTxsQueue::default(),
648 native_token: address::testing::nam(),
649 ethereum_height: None,
650 eth_events_queue: EthEventsQueue::default(),
651 storage_read_past_height_limit: Some(1000),
652 commit_only_data: CommitOnlyData::default(),
653 block_proposals_cache: CLruCache::new(
654 NonZeroUsize::new(10).unwrap(),
655 ),
656 }
657 }
658 }
659}
660
661#[allow(
662 clippy::arithmetic_side_effects,
663 clippy::cast_sign_loss,
664 clippy::cast_possible_wrap
665)]
666#[cfg(test)]
667mod tests {
668 use std::collections::BTreeMap;
669
670 use chrono::{TimeZone, Utc};
671 use merkle_tree::NO_DIFF_KEY_PREFIX;
672 use namada_core::address::InternalAddress;
673 use namada_core::borsh::{BorshDeserialize, BorshSerializeExt};
674 use namada_core::keccak::KeccakHash;
675 use namada_core::parameters::{EpochDuration, Parameters};
676 use namada_core::storage::DbKeySeg;
677 use namada_core::time::{self, DateTimeUtc, Duration};
678 use proptest::prelude::*;
679 use proptest::test_runner::Config;
680 use test_log::test;
683
684 use super::testing::*;
685 use super::*;
686
687 prop_compose! {
688 fn arb_and_epoch_duration_start_and_block()
693 (
694 start_height in 0..1000_u64,
695 start_time in 0..10000_i64,
696 min_num_of_blocks in 1..10_u64,
697 min_duration in 1..100_i64,
698 )
699 (
700 min_num_of_blocks in Just(min_num_of_blocks),
701 min_duration in Just(min_duration),
702 start_height in Just(start_height),
703 start_time in Just(start_time),
704 block_height in start_height + 1..(start_height + 2 * min_num_of_blocks),
705 block_time in start_time + 1..(start_time + 2 * min_duration),
706 min_blocks_delta in -(min_num_of_blocks as i64 - 1)..5,
708 min_duration_delta in -(min_duration - 1)..50,
710 ) -> (EpochDuration, BlockHeight, DateTimeUtc, BlockHeight, DateTimeUtc,
711 i64, i64) {
712 let epoch_duration = EpochDuration {
713 min_num_of_blocks,
714 min_duration: Duration::seconds(min_duration).into(),
715 };
716 (epoch_duration,
717 BlockHeight(start_height), Utc.timestamp_opt(start_time, 0).single().expect("expected valid timestamp").into(),
718 BlockHeight(block_height), Utc.timestamp_opt(block_time, 0).single().expect("expected valid timestamp").into(),
719 min_blocks_delta, min_duration_delta)
720 }
721 }
722
723 proptest! {
724 #![proptest_config(Config {
725 cases: 10,
726 .. Config::default()
727 })]
728 #[test]
735 fn update_epoch_after_its_duration(
736 (epoch_duration, start_height, start_time, block_height, block_time,
737 min_blocks_delta, min_duration_delta)
738 in arb_and_epoch_duration_start_and_block())
739 {
740 let mut state =TestState::default();
741 state.in_mem_mut().next_epoch_min_start_height=
742 start_height + epoch_duration.min_num_of_blocks;
743 state.in_mem_mut().next_epoch_min_start_time=
744 start_time + epoch_duration.min_duration;
745 let mut parameters = Parameters {
746 max_tx_bytes: 1024 * 1024,
747 max_proposal_bytes: Default::default(),
748 max_block_gas: 20_000_000,
749 epoch_duration: epoch_duration.clone(),
750 vp_allowlist: vec![],
751 tx_allowlist: vec![],
752 implicit_vp_code_hash: Some(Hash::zero()),
753 epochs_per_year: 100,
754 masp_epoch_multiplier: 2,
755 masp_fee_payment_gas_limit: 20_000,
756 gas_scale: 10_000_000,
757 minimum_gas_price: BTreeMap::default(),
758 is_native_token_transferable: true,
759 };
760 let height = state.in_mem().block.height;
762 state
763 .in_mem_mut()
764 .block
765 .pred_epochs
766 .new_epoch(height);
767
768 let epoch_before = state.in_mem().last_epoch;
769 assert_eq!(epoch_before, state.in_mem().block.epoch);
770
771 state.update_epoch(block_height, block_time, ¶meters).unwrap();
773
774 if block_height.0 - start_height.0
776 >= epoch_duration.min_num_of_blocks
777 && time::duration_passed(
778 block_time,
779 start_time,
780 epoch_duration.min_duration,
781 )
782 {
783 assert_eq!(state.in_mem().block.epoch, epoch_before);
785 assert_eq!(state.in_mem().update_epoch_blocks_delay, Some(2));
786
787 let block_height = block_height + 1;
788 let block_time = block_time + Duration::seconds(1);
789 state.update_epoch(block_height, block_time, ¶meters).unwrap();
790 assert_eq!(state.in_mem().block.epoch, epoch_before);
791 assert_eq!(state.in_mem().update_epoch_blocks_delay, Some(1));
792
793 let block_height = block_height + 1;
794 let block_time = block_time + Duration::seconds(1);
795 state.update_epoch(block_height, block_time, ¶meters).unwrap();
796 assert_eq!(state.in_mem().block.epoch, epoch_before.next());
797 assert!(state.in_mem().update_epoch_blocks_delay.is_none());
798
799 assert_eq!(state.in_mem().next_epoch_min_start_height,
800 block_height + epoch_duration.min_num_of_blocks);
801 assert_eq!(state.in_mem().next_epoch_min_start_time,
802 block_time + epoch_duration.min_duration);
803 assert_eq!(
804 state.in_mem().block.pred_epochs.get_epoch(BlockHeight(block_height.0 - 1)),
805 Some(epoch_before));
806 assert_eq!(
807 state.in_mem().block.pred_epochs.get_epoch(block_height),
808 Some(epoch_before.next()));
809 } else {
810 assert!(state.in_mem().update_epoch_blocks_delay.is_none());
811 assert_eq!(state.in_mem().block.epoch, epoch_before);
812 assert_eq!(
813 state.in_mem().block.pred_epochs.get_epoch(BlockHeight(block_height.0 - 1)),
814 Some(epoch_before));
815 assert_eq!(
816 state.in_mem().block.pred_epochs.get_epoch(block_height),
817 Some(epoch_before));
818 }
819 assert_eq!(state.in_mem().last_epoch, epoch_before);
821
822 parameters.epoch_duration.min_num_of_blocks =
824 (parameters.epoch_duration.min_num_of_blocks as i64 + min_blocks_delta) as u64;
825 let min_duration: i64 = parameters.epoch_duration.min_duration.0 as _;
826 parameters.epoch_duration.min_duration =
827 Duration::seconds(min_duration + min_duration_delta).into();
828
829 let epoch_before = state.in_mem().block.epoch;
831 let height_of_update = state.in_mem().next_epoch_min_start_height.0 ;
832 let time_of_update = state.in_mem().next_epoch_min_start_time;
833 let height_before_update = BlockHeight(height_of_update - 1);
834 let height_of_update = BlockHeight(height_of_update);
835 let time_before_update = time_of_update - Duration::seconds(1);
836
837 state.update_epoch(height_before_update, time_before_update, ¶meters).unwrap();
840 assert_eq!(state.in_mem().block.epoch, epoch_before);
841 assert!(state.in_mem().update_epoch_blocks_delay.is_none());
842 state.update_epoch(height_of_update, time_before_update, ¶meters).unwrap();
843 assert_eq!(state.in_mem().block.epoch, epoch_before);
844 assert!(state.in_mem().update_epoch_blocks_delay.is_none());
845 state.update_epoch(height_before_update, time_of_update, ¶meters).unwrap();
846 assert_eq!(state.in_mem().block.epoch, epoch_before);
847 assert!(state.in_mem().update_epoch_blocks_delay.is_none());
848
849 state.update_epoch(height_of_update, time_of_update, ¶meters).unwrap();
851 assert_eq!(state.in_mem().block.epoch, epoch_before);
852 assert_eq!(state.in_mem().update_epoch_blocks_delay, Some(2));
853
854 let height_of_update = height_of_update + 1;
856 let time_of_update = time_of_update + Duration::seconds(1);
857 state.update_epoch(height_of_update, time_of_update, ¶meters).unwrap();
858 assert_eq!(state.in_mem().block.epoch, epoch_before);
859 assert_eq!(state.in_mem().update_epoch_blocks_delay, Some(1));
860
861 let height_of_update = height_of_update + 1;
862 let time_of_update = time_of_update + Duration::seconds(1);
863 state.update_epoch(height_of_update, time_of_update, ¶meters).unwrap();
864 assert_eq!(state.in_mem().block.epoch, epoch_before.next());
865 assert!(state.in_mem().update_epoch_blocks_delay.is_none());
866 assert_eq!(state.in_mem().next_epoch_min_start_height,
868 height_of_update + parameters.epoch_duration.min_num_of_blocks);
869 assert_eq!(state.in_mem().next_epoch_min_start_time,
870 time_of_update + parameters.epoch_duration.min_duration);
871
872 let height_of_update = height_of_update + 1;
874 let time_of_update = time_of_update + Duration::seconds(1);
875 state.update_epoch(height_of_update, time_of_update, ¶meters).unwrap();
876 assert_eq!(state.in_mem().block.epoch, epoch_before.next());
877 }
878 }
879
880 fn test_key_1() -> Key {
881 Key::parse("testing1").unwrap()
882 }
883
884 fn test_key_2() -> Key {
885 Key::parse("testing2").unwrap()
886 }
887
888 fn diff_key_filter(key: &Key) -> bool {
889 key == &test_key_1()
890 }
891
892 #[test]
893 fn test_writing_without_diffs() {
894 let mut state = TestState::default();
895 assert_eq!(state.in_mem().block.height.0, 0);
896
897 (state.0.diff_key_filter) = diff_key_filter;
898
899 let key1 = test_key_1();
900 let val1 = 1u64;
901 let key2 = test_key_2();
902 let val2 = 2u64;
903
904 state.write(&key1, val1).unwrap();
906
907 let res = state.read::<u64>(&key1).unwrap().unwrap();
909 assert_eq!(res, val1);
910
911 let (res, _) = state.db_read(&key1).unwrap();
914 assert!(res.is_none());
915
916 state.write(&key2, val2).unwrap();
918
919 let res = state.read::<u64>(&key2).unwrap().unwrap();
921 assert_eq!(res, val2);
922
923 state.commit_block().unwrap();
925 state.in_mem_mut().block.height =
926 state.in_mem().block.height.next_height();
927
928 let (res1, _) = state.db_read(&key1).unwrap();
930 let res1 = u64::try_from_slice(&res1.unwrap()).unwrap();
931 assert_eq!(res1, val1);
932
933 let is_merklized1 = state.in_mem().block.tree.has_key(&key1).unwrap();
935 assert!(is_merklized1);
936
937 let res2 = state.read::<u64>(&key2).unwrap().unwrap();
940 assert_eq!(res2, val2);
941 let res2 = state.db().read_subspace_val(&key2).unwrap().unwrap();
942 let res2 = u64::try_from_slice(&res2).unwrap();
943 assert_eq!(res2, val2);
944
945 let is_merklized2 = state.in_mem().block.tree.has_key(&key2).unwrap();
947 assert!(!is_merklized2);
948 let no_diff_key2 =
949 Key::from(NO_DIFF_KEY_PREFIX.to_string().to_db_key()).join(&key2);
950 let is_merklized2 =
951 state.in_mem().block.tree.has_key(&no_diff_key2).unwrap();
952 assert!(is_merklized2);
953
954 let res1 = state
956 .db()
957 .read_diffs_val(&key1, Default::default(), true)
958 .unwrap();
959 assert!(res1.is_none());
960
961 let res1 = state
962 .db()
963 .read_diffs_val(&key1, Default::default(), false)
964 .unwrap()
965 .unwrap();
966 let res1 = u64::try_from_slice(&res1).unwrap();
967 assert_eq!(res1, val1);
968
969 let res2 = state
972 .db()
973 .read_diffs_val(&key2, BlockHeight(0), true)
974 .unwrap();
975 assert!(res2.is_none());
976 let res2 = state
977 .db()
978 .read_diffs_val(&key2, BlockHeight(0), false)
979 .unwrap()
980 .unwrap();
981 let res2 = u64::try_from_slice(&res2).unwrap();
982 assert_eq!(res2, val2);
983
984 state.delete(&key1).unwrap();
986 state.delete(&key2).unwrap();
987
988 state.commit_block().unwrap();
990 state.in_mem_mut().block.height =
991 state.in_mem().block.height.next_height();
992
993 let res1 = state.read::<u64>(&key1).unwrap();
995 let res2 = state.read::<u64>(&key2).unwrap();
996 assert!(res1.is_none() && res2.is_none());
997 let res1 = state.db().read_subspace_val(&key1).unwrap();
998 let res2 = state.db().read_subspace_val(&key2).unwrap();
999 assert!(res1.is_none() && res2.is_none());
1000
1001 let is_merklized1 = state.in_mem().block.tree.has_key(&key1).unwrap();
1003 let is_merklized2 =
1004 state.in_mem().block.tree.has_key(&no_diff_key2).unwrap();
1005 assert!(!is_merklized1 && !is_merklized2);
1006
1007 let res1 = state
1009 .db()
1010 .read_diffs_val(&key1, BlockHeight(0), true)
1011 .unwrap();
1012 assert!(res1.is_none());
1013
1014 let res1 = state
1015 .db()
1016 .read_diffs_val(&key1, BlockHeight(0), false)
1017 .unwrap()
1018 .unwrap();
1019 let res1 = u64::try_from_slice(&res1).unwrap();
1020 assert_eq!(res1, val1);
1021
1022 let res1 = state
1023 .db()
1024 .read_diffs_val(&key1, BlockHeight(1), true)
1025 .unwrap()
1026 .unwrap();
1027 let res1 = u64::try_from_slice(&res1).unwrap();
1028 assert_eq!(res1, val1);
1029
1030 let res1 = state
1031 .db()
1032 .read_diffs_val(&key1, BlockHeight(1), false)
1033 .unwrap();
1034 assert!(res1.is_none());
1035
1036 let res2 = state
1038 .db()
1039 .read_diffs_val(&key2, BlockHeight(0), true)
1040 .unwrap();
1041 assert!(res2.is_none());
1042 let res2 = state
1043 .db()
1044 .read_diffs_val(&key2, BlockHeight(0), false)
1045 .unwrap();
1046 assert!(res2.is_none());
1047
1048 let res2 = state
1051 .db()
1052 .read_diffs_val(&key2, BlockHeight(1), true)
1053 .unwrap()
1054 .unwrap();
1055 let res2 = u64::try_from_slice(&res2).unwrap();
1056 assert_eq!(res2, val2);
1057 let res2 = state
1058 .db()
1059 .read_diffs_val(&key2, BlockHeight(1), false)
1060 .unwrap();
1061 assert!(res2.is_none());
1062 }
1063
1064 proptest! {
1065 #![proptest_config(Config {
1067 cases: 10,
1068 .. Config::default()
1069 })]
1070 #[test]
1071 fn test_prefix_iters(
1072 key_vals in arb_key_vals(30),
1073 ) {
1074 test_prefix_iters_aux(key_vals)
1075 }
1076 }
1077
1078 fn test_prefix_iters_aux(kvs: Vec<KeyVal<i8>>) {
1081 let mut s = TestState::default();
1082
1083 let (tx_kvs, rest): (Vec<_>, Vec<_>) = kvs
1085 .into_iter()
1086 .partition(|(_key, val)| matches!(val, Level::TxWriteLog(_)));
1087 let (block_kvs, storage_kvs): (Vec<_>, Vec<_>) = rest
1089 .into_iter()
1090 .partition(|(_key, val)| matches!(val, Level::BlockWriteLog(_)));
1091
1092 apply_to_state(&mut s, &storage_kvs);
1094 apply_to_state(&mut s, &block_kvs);
1095 apply_to_state(&mut s, &tx_kvs);
1096
1097 let mut expected_pre = BTreeMap::new();
1099 for (key, val) in storage_kvs {
1100 if let Level::Storage(val) = val {
1101 expected_pre.insert(key, val);
1102 }
1103 }
1104 for (key, val) in &block_kvs {
1105 if let Level::BlockWriteLog(WlMod::Write(val)) = val {
1106 expected_pre.insert(key.clone(), *val);
1107 }
1108 }
1109 for (key, val) in &block_kvs {
1110 if let Level::BlockWriteLog(WlMod::Delete) = val {
1112 expected_pre.remove(key);
1113 } else if let Level::BlockWriteLog(WlMod::DeletePrefix) = val {
1114 expected_pre.retain(|expected_key, _val| {
1115 expected_key.is_validity_predicate().is_some()
1117 || expected_key.split_prefix(key).is_none()
1118 })
1119 }
1120 }
1121
1122 let (iter_pre, _gas) =
1124 iter_prefix_pre(s.write_log(), s.db(), &storage::Key::default())
1125 .unwrap();
1126 let mut read_pre = BTreeMap::new();
1127 for (key, val, _gas) in iter_pre {
1128 let key = storage::Key::parse(key).unwrap();
1129 let val: i8 = BorshDeserialize::try_from_slice(&val).unwrap();
1130 read_pre.insert(key, val);
1131 }
1132
1133 let keys_to_string = |kvs: &BTreeMap<storage::Key, i8>| {
1135 kvs.iter()
1136 .map(|(key, val)| (key.to_string(), *val))
1137 .collect::<Vec<_>>()
1138 };
1139 dbg!(keys_to_string(&expected_pre), keys_to_string(&read_pre));
1140 let mut expected_post = expected_pre.clone();
1142 itertools::assert_equal(expected_pre, read_pre);
1143
1144 for (key, val) in &tx_kvs {
1146 if let Level::TxWriteLog(WlMod::Write(val)) = val {
1147 expected_post.insert(key.clone(), *val);
1148 }
1149 }
1150 for (key, val) in &tx_kvs {
1151 if let Level::TxWriteLog(WlMod::Delete) = val {
1153 expected_post.remove(key);
1154 } else if let Level::TxWriteLog(WlMod::DeletePrefix) = val {
1155 expected_post.retain(|expected_key, _val| {
1156 expected_key.is_validity_predicate().is_some()
1158 || expected_key.split_prefix(key).is_none()
1159 })
1160 }
1161 }
1162
1163 let (iter_post, _gas) =
1165 iter_prefix_post(s.write_log(), s.db(), &storage::Key::default())
1166 .unwrap();
1167 let mut read_post = BTreeMap::new();
1168 for (key, val, _gas) in iter_post {
1169 let key = storage::Key::parse(key).unwrap();
1170 let val: i8 = BorshDeserialize::try_from_slice(&val).unwrap();
1171 read_post.insert(key, val);
1172 }
1173 dbg!(keys_to_string(&expected_post), keys_to_string(&read_post));
1174 itertools::assert_equal(expected_post, read_post);
1175 }
1176
1177 fn apply_to_state(s: &mut TestState, kvs: &[KeyVal<i8>]) {
1178 for (key, val) in kvs {
1180 match val {
1181 Level::TxWriteLog(WlMod::Delete | WlMod::DeletePrefix)
1182 | Level::BlockWriteLog(WlMod::Delete | WlMod::DeletePrefix) => {
1183 }
1184 Level::TxWriteLog(WlMod::Write(val)) => {
1185 let _ = s
1186 .write_log_mut()
1187 .write(key, val.serialize_to_vec())
1188 .unwrap();
1189 }
1190 Level::BlockWriteLog(WlMod::Write(val)) => {
1191 s.write_log_mut()
1192 .protocol_write(key, val.serialize_to_vec())
1194 .unwrap();
1195 }
1196 Level::Storage(val) => {
1197 s.db_write(key, val.serialize_to_vec()).unwrap();
1198 }
1199 }
1200 }
1201 for (key, val) in kvs {
1203 match val {
1204 Level::TxWriteLog(WlMod::Delete) => {
1205 let _ = s.write_log_mut().delete(key).unwrap();
1206 }
1207 Level::BlockWriteLog(WlMod::Delete) => {
1208 s.delete(key).unwrap();
1209 }
1210 Level::TxWriteLog(WlMod::DeletePrefix) => {
1211 let keys =
1213 namada_storage::iter_prefix_bytes(s, key.clone())
1214 .unwrap()
1215 .map(|res| {
1216 let (key, _val) = res.unwrap();
1217 key
1218 })
1219 .collect::<Vec<storage::Key>>();
1220 for key in keys {
1222 if key.is_validity_predicate().is_none() {
1224 let _ = s.write_log_mut().delete(&key).unwrap();
1225 }
1226 }
1227 }
1228 Level::BlockWriteLog(WlMod::DeletePrefix) => {
1229 s.delete_prefix(key).unwrap();
1230 }
1231 _ => {}
1232 }
1233 }
1234 }
1235
1236 type KeyVal<VAL> = (storage::Key, Level<VAL>);
1238
1239 #[derive(Clone, Copy, Debug)]
1241 enum Level<VAL> {
1242 TxWriteLog(WlMod<VAL>),
1243 BlockWriteLog(WlMod<VAL>),
1244 Storage(VAL),
1245 }
1246
1247 #[derive(Clone, Copy, Debug)]
1249 enum WlMod<VAL> {
1250 Write(VAL),
1251 Delete,
1252 DeletePrefix,
1253 }
1254
1255 fn arb_key_vals(len: usize) -> impl Strategy<Value = Vec<KeyVal<i8>>> {
1256 let storage_kvs = prop::collection::vec(
1258 (storage::testing::arb_key(), any::<i8>()),
1259 1..len,
1260 )
1261 .prop_map(|kvs| {
1262 kvs.into_iter()
1263 .map(|(mut key, val)| {
1264 if let DbKeySeg::AddressSeg(Address::Internal(
1265 InternalAddress::EthBridgePool,
1266 )) = key.segments[0]
1267 {
1268 key.segments.insert(
1272 1,
1273 DbKeySeg::StringSeg(
1274 KeccakHash::default().to_string(),
1275 ),
1276 );
1277 }
1278 (key, Level::Storage(val))
1279 })
1280 .collect::<Vec<_>>()
1281 });
1282
1283 let overrides = prop::collection::vec(
1285 (any::<prop::sample::Index>(), any::<i8>(), any::<bool>()),
1286 1..len / 2,
1287 );
1288
1289 let deletes = prop::collection::vec(
1291 (any::<prop::sample::Index>(), any::<bool>()),
1292 1..len / 3,
1293 );
1294
1295 let delete_prefix = prop::collection::vec(
1297 (
1298 any::<prop::sample::Index>(),
1299 any::<bool>(),
1300 (2_usize..4),
1304 ),
1305 1..len / 4,
1306 );
1307
1308 (storage_kvs, overrides, deletes, delete_prefix).prop_map(
1310 |(mut kvs, overrides, deletes, delete_prefix)| {
1311 for (ix, val, is_tx) in overrides {
1312 let (key, _) = ix.get(&kvs);
1313 let wl_mod = WlMod::Write(val);
1314 let lvl = if is_tx {
1315 Level::TxWriteLog(wl_mod)
1316 } else {
1317 Level::BlockWriteLog(wl_mod)
1318 };
1319 kvs.push((key.clone(), lvl));
1320 }
1321 for (ix, is_tx) in deletes {
1322 let (key, _) = ix.get(&kvs);
1323 if key.is_validity_predicate().is_some() {
1326 continue;
1327 }
1328 let wl_mod = WlMod::Delete;
1329 let lvl = if is_tx {
1330 Level::TxWriteLog(wl_mod)
1331 } else {
1332 Level::BlockWriteLog(wl_mod)
1333 };
1334 kvs.push((key.clone(), lvl));
1335 }
1336 for (ix, is_tx, num_of_seg_to_drop) in delete_prefix {
1337 let (key, _) = ix.get(&kvs);
1338 let wl_mod = WlMod::DeletePrefix;
1339 let lvl = if is_tx {
1340 Level::TxWriteLog(wl_mod)
1341 } else {
1342 Level::BlockWriteLog(wl_mod)
1343 };
1344 let num_of_seg_to_keep = std::cmp::max(
1346 1,
1347 key.segments
1348 .len()
1349 .checked_sub(num_of_seg_to_drop)
1350 .unwrap_or_default(),
1351 );
1352 let prefix = storage::Key {
1353 segments: key
1354 .segments
1355 .iter()
1356 .take(num_of_seg_to_keep)
1357 .cloned()
1358 .collect(),
1359 };
1360 kvs.push((prefix, lvl));
1361 }
1362 kvs
1363 },
1364 )
1365 }
1366}