@@ -20,6 +20,7 @@ pub use piecrust::{
20
20
} ;
21
21
22
22
use alloc:: vec:: Vec ;
23
+ use std:: collections:: HashMap ;
23
24
use std:: fmt:: { self , Debug , Formatter } ;
24
25
use std:: path:: { Path , PathBuf } ;
25
26
use std:: thread;
@@ -43,17 +44,23 @@ pub mod host_queries;
43
44
/// executing smart contracts, and interfacing with host functions. It supports
44
45
/// both persistent and ephemeral sessions for handling transactions, contract
45
46
/// queries and contract deployments.
46
- pub struct VM ( PiecrustVM ) ;
47
+ pub struct VM {
48
+ inner : PiecrustVM ,
49
+ hq_activation : HashMap < String , u64 > ,
50
+ }
47
51
48
52
impl From < PiecrustVM > for VM {
49
53
fn from ( piecrust_vm : PiecrustVM ) -> Self {
50
- VM ( piecrust_vm)
54
+ VM {
55
+ inner : piecrust_vm,
56
+ hq_activation : HashMap :: new ( ) ,
57
+ }
51
58
}
52
59
}
53
60
54
61
impl Debug for VM {
55
62
fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
56
- self . 0 . fmt ( f)
63
+ self . inner . fmt ( f)
57
64
}
58
65
}
59
66
@@ -111,6 +118,46 @@ impl VM {
111
118
Ok ( vm)
112
119
}
113
120
121
+ /// Sets the activation height for a specific host query.
122
+ ///
123
+ /// This method associates a previously registered host query with a block
124
+ /// height at which it becomes active. Before this activation height,
125
+ /// the host query will be excluded from session execution.
126
+ ///
127
+ /// **Note:** The specified host query must already be registered in the
128
+ /// global host queries registry before calling this method.
129
+ ///
130
+ /// # Arguments
131
+ /// * `host_query` - The name of the host query to activate.
132
+ /// * `activation` - The block height at which the host query becomes
133
+ /// active.
134
+ ///
135
+ /// # Panics
136
+ /// This method will panic if the provided `host_query` is not already
137
+ /// registered in the global host queries registry.
138
+ ///
139
+ /// # Examples
140
+ /// ```rust
141
+ /// use dusk_vm::VM;
142
+ /// use dusk_core::abi::Query;
143
+ ///
144
+ /// let mut vm = VM::ephemeral().unwrap();
145
+ /// vm.with_hq_activation(Query::KECCAK256, 100);
146
+ /// ```
147
+ pub fn with_hq_activation < S : Into < String > > (
148
+ & mut self ,
149
+ host_query : S ,
150
+ activation : u64 ,
151
+ ) {
152
+ let host_query = host_query. into ( ) ;
153
+ if self . inner . host_queries ( ) . get ( & host_query) . is_none ( ) {
154
+ panic ! (
155
+ "Host query '{host_query}' must be registered before setting activation"
156
+ ) ;
157
+ }
158
+ self . hq_activation . insert ( host_query, activation) ;
159
+ }
160
+
114
161
/// Creates a new session for transaction execution.
115
162
///
116
163
/// This method initializes a session with a specific base state commit,
@@ -157,12 +204,22 @@ impl VM {
157
204
chain_id : u8 ,
158
205
block_height : u64 ,
159
206
) -> Result < Session , Error > {
160
- self . 0 . session (
161
- SessionData :: builder ( )
162
- . base ( base)
163
- . insert ( Metadata :: CHAIN_ID , chain_id) ?
164
- . insert ( Metadata :: BLOCK_HEIGHT , block_height) ?,
165
- )
207
+ let mut builder = SessionData :: builder ( )
208
+ . base ( base)
209
+ . insert ( Metadata :: CHAIN_ID , chain_id) ?
210
+ . insert ( Metadata :: BLOCK_HEIGHT , block_height) ?;
211
+ // If the block height is greater than 0, exclude host queries
212
+ // that are not yet activated.
213
+ // We don't want to exclude host queries for block height 0 because it's
214
+ // used for query sessions
215
+ if block_height > 0 {
216
+ for ( host_query, & activation) in & self . hq_activation {
217
+ if block_height < activation {
218
+ builder = builder. exclude_hq ( host_query. clone ( ) ) ;
219
+ }
220
+ }
221
+ }
222
+ self . inner . session ( builder)
166
223
}
167
224
168
225
/// Initializes a session for setting up the genesis block.
@@ -188,7 +245,7 @@ impl VM {
188
245
/// let genesis_session = vm.genesis_session(CHAIN_ID);
189
246
/// ```
190
247
pub fn genesis_session ( & self , chain_id : u8 ) -> Session {
191
- self . 0
248
+ self . inner
192
249
. session (
193
250
SessionData :: builder ( )
194
251
. insert ( Metadata :: CHAIN_ID , chain_id)
@@ -209,56 +266,57 @@ impl VM {
209
266
/// # Returns
210
267
/// A vector of commits.
211
268
pub fn commits ( & self ) -> Vec < [ u8 ; 32 ] > {
212
- self . 0 . commits ( )
269
+ self . inner . commits ( )
213
270
}
214
271
215
272
/// Deletes a specified commit from the VM.
216
273
///
217
274
/// # Arguments
218
275
/// * `commit` - The commit to be deleted.
219
276
pub fn delete_commit ( & self , root : [ u8 ; 32 ] ) -> Result < ( ) , Error > {
220
- self . 0 . delete_commit ( root)
277
+ self . inner . delete_commit ( root)
221
278
}
222
279
223
280
/// Finalizes a specified commit, applying its state changes permanently.
224
281
///
225
282
/// # Arguments
226
283
/// * `commit` - The commit to be finalized.
227
284
pub fn finalize_commit ( & self , root : [ u8 ; 32 ] ) -> Result < ( ) , Error > {
228
- self . 0 . finalize_commit ( root)
285
+ self . inner . finalize_commit ( root)
229
286
}
230
287
231
288
/// Returns the root directory of the VM.
232
289
///
233
- /// This is either the directory passed in by using [`new`], or the
234
- /// temporary directory created using [`ephemeral`].
290
+ /// This is either the directory passed in by using [`Self:: new`], or the
291
+ /// temporary directory created using [`Self:: ephemeral`].
235
292
pub fn root_dir ( & self ) -> & Path {
236
- self . 0 . root_dir ( )
293
+ self . inner . root_dir ( )
237
294
}
238
295
239
296
/// Returns a reference to the synchronization thread.
240
297
pub fn sync_thread ( & self ) -> & thread:: Thread {
241
- self . 0 . sync_thread ( )
298
+ self . inner . sync_thread ( )
242
299
}
243
300
244
301
fn register_host_queries ( & mut self ) {
245
- self . 0 . register_host_query ( Query :: HASH , host_hash) ;
246
- self . 0
302
+ self . inner . register_host_query ( Query :: HASH , host_hash) ;
303
+ self . inner
247
304
. register_host_query ( Query :: POSEIDON_HASH , host_poseidon_hash) ;
248
- self . 0
305
+ self . inner
249
306
. register_host_query ( Query :: VERIFY_PLONK , host_verify_plonk) ;
250
- self . 0 . register_host_query (
307
+ self . inner . register_host_query (
251
308
Query :: VERIFY_GROTH16_BN254 ,
252
309
host_verify_groth16_bn254,
253
310
) ;
254
- self . 0
311
+ self . inner
255
312
. register_host_query ( Query :: VERIFY_SCHNORR , host_verify_schnorr) ;
256
- self . 0
313
+ self . inner
257
314
. register_host_query ( Query :: VERIFY_BLS , host_verify_bls) ;
258
- self . 0 . register_host_query (
315
+ self . inner . register_host_query (
259
316
Query :: VERIFY_BLS_MULTISIG ,
260
317
host_verify_bls_multisig,
261
318
) ;
262
- self . 0 . register_host_query ( Query :: KECCAK256 , host_keccak256) ;
319
+ self . inner
320
+ . register_host_query ( Query :: KECCAK256 , host_keccak256) ;
263
321
}
264
322
}
0 commit comments