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}