Skip to content

Commit 8f49e5b

Browse files
authored
Merge pull request #3829 from dusk-network/vm_hostqueries_activation
vm_hostqueries_activation
2 parents 07a5074 + 5d8062b commit 8f49e5b

File tree

7 files changed

+102
-30
lines changed

7 files changed

+102
-30
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ jubjub-schnorr = { version = "0.6", default-features = false }
7272
kadcast = "0.7"
7373
phoenix-circuits = { version = "0.6", default-features = false }
7474
phoenix-core = { version = "0.34.0", default-features = false }
75-
piecrust = "0.29.0-rc.0"
75+
piecrust = "0.29.0-rc.1"
7676
piecrust-uplink = "0.19.0-rc.0"
7777
poseidon-merkle = "0.8"
7878

rusk/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212
- Add support for `TransactionData::Blob`
1313
- Add `mempool_nonce` field to `/on/account/status` response
1414
- Add `status` to GQL block fields
15+
- Add activaction height for host queries
1516

1617
### Changed
1718

rusk/src/lib/node/rusk.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,15 @@ impl Rusk {
7474
let mut base_commit = [0u8; 32];
7575
base_commit.copy_from_slice(&base_commit_bytes);
7676

77-
let vm = Arc::new(VM::new(dir)?);
77+
let mut vm = VM::new(dir)?;
78+
for (feat, activation) in vm_config.features() {
79+
let feat = feat.to_ascii_lowercase();
80+
if let Some(hq_name) = feat.strip_prefix("hq_") {
81+
vm.with_hq_activation(hq_name, *activation);
82+
}
83+
}
84+
85+
let vm = Arc::new(vm);
7886

7987
let tip = Arc::new(RwLock::new(RuskTip {
8088
current: base_commit,

rusk/src/lib/node/vm/config.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//
55
// Copyright (c) DUSK NETWORK. All rights reserved.
66

7-
use std::collections::HashMap;
7+
use std::collections::{hash_map::Iter, HashMap};
88
use std::time::Duration;
99

1010
use dusk_vm::ExecutionConfig;
@@ -131,6 +131,10 @@ impl Config {
131131
}
132132
}
133133

134+
pub fn features(&self) -> Iter<String, u64> {
135+
self.features.iter()
136+
}
137+
134138
pub fn feature(&self, feature: &str) -> Option<u64> {
135139
self.features
136140
.iter()

vm/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
- Add support for `TransactionData::Blob`
1313
- Add `keccak256` host query function [#3774]
14+
- Add activaction height for host queries
1415

1516
## [1.3.0] - 2025-04-17
1617

vm/src/lib.rs

Lines changed: 83 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub use piecrust::{
2020
};
2121

2222
use alloc::vec::Vec;
23+
use std::collections::HashMap;
2324
use std::fmt::{self, Debug, Formatter};
2425
use std::path::{Path, PathBuf};
2526
use std::thread;
@@ -43,17 +44,23 @@ pub mod host_queries;
4344
/// executing smart contracts, and interfacing with host functions. It supports
4445
/// both persistent and ephemeral sessions for handling transactions, contract
4546
/// queries and contract deployments.
46-
pub struct VM(PiecrustVM);
47+
pub struct VM {
48+
inner: PiecrustVM,
49+
hq_activation: HashMap<String, u64>,
50+
}
4751

4852
impl From<PiecrustVM> for VM {
4953
fn from(piecrust_vm: PiecrustVM) -> Self {
50-
VM(piecrust_vm)
54+
VM {
55+
inner: piecrust_vm,
56+
hq_activation: HashMap::new(),
57+
}
5158
}
5259
}
5360

5461
impl Debug for VM {
5562
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
56-
self.0.fmt(f)
63+
self.inner.fmt(f)
5764
}
5865
}
5966

@@ -111,6 +118,46 @@ impl VM {
111118
Ok(vm)
112119
}
113120

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+
114161
/// Creates a new session for transaction execution.
115162
///
116163
/// This method initializes a session with a specific base state commit,
@@ -157,12 +204,22 @@ impl VM {
157204
chain_id: u8,
158205
block_height: u64,
159206
) -> 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)
166223
}
167224

168225
/// Initializes a session for setting up the genesis block.
@@ -188,7 +245,7 @@ impl VM {
188245
/// let genesis_session = vm.genesis_session(CHAIN_ID);
189246
/// ```
190247
pub fn genesis_session(&self, chain_id: u8) -> Session {
191-
self.0
248+
self.inner
192249
.session(
193250
SessionData::builder()
194251
.insert(Metadata::CHAIN_ID, chain_id)
@@ -209,56 +266,57 @@ impl VM {
209266
/// # Returns
210267
/// A vector of commits.
211268
pub fn commits(&self) -> Vec<[u8; 32]> {
212-
self.0.commits()
269+
self.inner.commits()
213270
}
214271

215272
/// Deletes a specified commit from the VM.
216273
///
217274
/// # Arguments
218275
/// * `commit` - The commit to be deleted.
219276
pub fn delete_commit(&self, root: [u8; 32]) -> Result<(), Error> {
220-
self.0.delete_commit(root)
277+
self.inner.delete_commit(root)
221278
}
222279

223280
/// Finalizes a specified commit, applying its state changes permanently.
224281
///
225282
/// # Arguments
226283
/// * `commit` - The commit to be finalized.
227284
pub fn finalize_commit(&self, root: [u8; 32]) -> Result<(), Error> {
228-
self.0.finalize_commit(root)
285+
self.inner.finalize_commit(root)
229286
}
230287

231288
/// Returns the root directory of the VM.
232289
///
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`].
235292
pub fn root_dir(&self) -> &Path {
236-
self.0.root_dir()
293+
self.inner.root_dir()
237294
}
238295

239296
/// Returns a reference to the synchronization thread.
240297
pub fn sync_thread(&self) -> &thread::Thread {
241-
self.0.sync_thread()
298+
self.inner.sync_thread()
242299
}
243300

244301
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
247304
.register_host_query(Query::POSEIDON_HASH, host_poseidon_hash);
248-
self.0
305+
self.inner
249306
.register_host_query(Query::VERIFY_PLONK, host_verify_plonk);
250-
self.0.register_host_query(
307+
self.inner.register_host_query(
251308
Query::VERIFY_GROTH16_BN254,
252309
host_verify_groth16_bn254,
253310
);
254-
self.0
311+
self.inner
255312
.register_host_query(Query::VERIFY_SCHNORR, host_verify_schnorr);
256-
self.0
313+
self.inner
257314
.register_host_query(Query::VERIFY_BLS, host_verify_bls);
258-
self.0.register_host_query(
315+
self.inner.register_host_query(
259316
Query::VERIFY_BLS_MULTISIG,
260317
host_verify_bls_multisig,
261318
);
262-
self.0.register_host_query(Query::KECCAK256, host_keccak256);
319+
self.inner
320+
.register_host_query(Query::KECCAK256, host_keccak256);
263321
}
264322
}

0 commit comments

Comments
 (0)