namada_vp_env/
lib.rs

1//! Validity predicate environment contains functions that can be called from
2//! inside validity predicates.
3
4#![doc(html_favicon_url = "https://dev.namada.net/master/favicon.png")]
5#![doc(html_logo_url = "https://dev.namada.net/master/rustdoc-logo.png")]
6#![deny(rustdoc::broken_intra_doc_links)]
7#![deny(rustdoc::private_intra_doc_links)]
8#![warn(
9    missing_docs,
10    rust_2018_idioms,
11    clippy::cast_sign_loss,
12    clippy::cast_possible_truncation,
13    clippy::cast_possible_wrap,
14    clippy::cast_lossless,
15    clippy::arithmetic_side_effects,
16    clippy::dbg_macro,
17    clippy::print_stdout,
18    clippy::print_stderr
19)]
20
21pub mod collection_validation;
22
23use namada_core::address::Address;
24use namada_core::borsh::BorshDeserialize;
25use namada_core::chain::ChainId;
26pub use namada_core::chain::{BlockHeader, BlockHeight, Epoch, Epochs};
27use namada_core::hash::Hash;
28use namada_events::{Event, EventType};
29use namada_gas::Gas;
30pub use namada_storage::{Error, Key, Result, StorageRead, TxIndex};
31use namada_tx::BatchedTxRef;
32
33/// Validity predicate's environment is available for native VPs and WASM VPs
34pub trait VpEnv<'view>
35where
36    Self: 'view,
37{
38    /// Storage read prefix iterator
39    type PrefixIter<'iter>
40    where
41        Self: 'iter;
42
43    /// Type to read storage state before the transaction execution
44    type Pre: StorageRead<PrefixIter<'view> = Self::PrefixIter<'view>>;
45
46    /// Type to read storage state after the transaction execution
47    type Post: StorageRead<PrefixIter<'view> = Self::PrefixIter<'view>>;
48
49    /// Read storage state before the transaction execution
50    fn pre(&'view self) -> Self::Pre;
51
52    /// Read storage state after the transaction execution
53    fn post(&'view self) -> Self::Post;
54
55    /// Storage read temporary state Borsh encoded value (after tx execution).
56    /// It will try to read from only the write log and then decode it if
57    /// found.
58    fn read_temp<T: BorshDeserialize>(&self, key: &Key) -> Result<Option<T>>;
59
60    /// Storage read temporary state raw bytes (after tx execution). It will try
61    /// to read from only the write log.
62    fn read_bytes_temp(&self, key: &Key) -> Result<Option<Vec<u8>>>;
63
64    /// Getting the chain ID.
65    fn get_chain_id(&self) -> Result<ChainId>;
66
67    /// Getting the block height. The height is that of the block to which the
68    /// current transaction is being applied if we are in between the
69    /// `FinalizeBlock` and the `Commit` phases. For all the other phases we
70    /// return the block height of next block that the consensus process
71    /// will decide upon (i.e. the block height of the last committed block
72    /// + 1)
73    fn get_block_height(&self) -> Result<BlockHeight>;
74
75    /// Getting the block header.
76    fn get_block_header(
77        &self,
78        height: BlockHeight,
79    ) -> Result<Option<BlockHeader>>;
80
81    /// Getting the block epoch. The epoch is that of the block to which the
82    /// current transaction is being applied.
83    fn get_block_epoch(&self) -> Result<Epoch>;
84
85    /// Get the shielded transaction index.
86    fn get_tx_index(&self) -> Result<TxIndex>;
87
88    /// Get the address of the native token.
89    fn get_native_token(&self) -> Result<Address>;
90
91    /// Given the information about predecessor block epochs
92    fn get_pred_epochs(&self) -> namada_storage::Result<Epochs>;
93
94    /// Get the events emitted by the current tx.
95    fn get_events(&self, event_type: &EventType) -> Result<Vec<Event>>;
96
97    /// Storage prefix iterator, ordered by storage keys. It will try to get an
98    /// iterator from the storage.
99    fn iter_prefix<'iter>(
100        &'iter self,
101        prefix: &Key,
102    ) -> Result<Self::PrefixIter<'iter>>;
103
104    /// Evaluate a validity predicate with given data. The address, changed
105    /// storage keys and verifiers will have the same values as the input to
106    /// caller's validity predicate.
107    ///
108    /// If the execution fails for whatever reason, this will return `false`.
109    /// Otherwise returns the result of evaluation.
110    fn eval(&self, vp_code: Hash, input_data: BatchedTxRef<'_>) -> Result<()>;
111
112    /// Get a tx hash
113    fn get_tx_code_hash(&self) -> Result<Option<Hash>>;
114
115    /// Charge the provided gas for the current vp
116    fn charge_gas(&self, used_gas: Gas) -> Result<()>;
117
118    // ---- Methods below have default implementation via `pre/post` ----
119
120    /// Storage read prior state Borsh encoded value (before tx execution). It
121    /// will try to read from the storage and decode it if found.
122    fn read_pre<T: BorshDeserialize>(
123        &'view self,
124        key: &Key,
125    ) -> Result<Option<T>> {
126        self.pre().read(key)
127    }
128
129    /// Storage read prior state raw bytes (before tx execution). It
130    /// will try to read from the storage.
131    fn read_bytes_pre(&'view self, key: &Key) -> Result<Option<Vec<u8>>> {
132        self.pre().read_bytes(key)
133    }
134
135    /// Storage read posterior state Borsh encoded value (after tx execution).
136    /// It will try to read from the write log first and if no entry found
137    /// then from the storage and then decode it if found.
138    fn read_post<T: BorshDeserialize>(
139        &'view self,
140        key: &Key,
141    ) -> Result<Option<T>> {
142        self.post().read(key)
143    }
144
145    /// Storage read posterior state raw bytes (after tx execution). It will try
146    /// to read from the write log first and if no entry found then from the
147    /// storage.
148    fn read_bytes_post(&'view self, key: &Key) -> Result<Option<Vec<u8>>> {
149        self.post().read_bytes(key)
150    }
151
152    /// Storage `has_key` in prior state (before tx execution). It will try to
153    /// read from the storage.
154    fn has_key_pre(&'view self, key: &Key) -> Result<bool> {
155        self.pre().has_key(key)
156    }
157
158    /// Storage `has_key` in posterior state (after tx execution). It will try
159    /// to check the write log first and if no entry found then the storage.
160    fn has_key_post(&'view self, key: &Key) -> Result<bool> {
161        self.post().has_key(key)
162    }
163}