Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
- Documented the `sorted_array` lookup sortedness contract and added linear assertion helpers for proving word, key, and half-key ordering ([#3308](https://github.com/0xMiden/miden-vm/pull/3308)).
- Added trusted sparse MAST forest serialization for trace replay payloads ([#3313](https://github.com/0xMiden/miden-vm/pull/3313)).
- [BREAKING] MAST forest payloads now include sorted root and dependency digests, so commitment inputs round trip ([#3294](https://github.com/0xMiden/miden-vm/pull/3294)).
- [BREAKING] MAST forest and package code digests now commit to both public roots and external dependencies ([#3311](https://github.com/0xMiden/miden-vm/pull/3311)).

## v0.24.0 (2026-06-24)

Expand Down
21 changes: 21 additions & 0 deletions core/src/advice/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use serde::{Deserialize, Serialize};

use crate::{
Felt, WORD_SIZE, Word,
crypto::hash::Poseidon2,
serde::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable},
};

Expand Down Expand Up @@ -87,6 +88,26 @@ impl AdviceMap {
})
}

/// Returns a commitment to this advice map.
///
/// Entries are committed in key order. Each entry is hashed as the key elements followed by the
/// value elements. [`Poseidon2::hash_elements`] binds the entry length, and
/// [`Poseidon2::merge_many`] folds the ordered entry commitments into the final map
/// commitment.
pub fn commitment(&self) -> Word {
let entry_commitments = self
.iter()
.map(|(key, values)| {
let mut elements = Vec::with_capacity(WORD_SIZE + values.len());
elements.extend_from_slice(key.as_elements());
elements.extend_from_slice(values);
Poseidon2::hash_elements(&elements)
})
.collect::<Vec<_>>();

Poseidon2::merge_many(&entry_commitments)
}
Comment thread
bobbinth marked this conversation as resolved.

/// Gets the given key's corresponding entry in the map for in-place manipulation.
pub fn entry(&mut self, key: Word) -> Entry<'_, Word, Arc<[Felt]>> {
self.0.entry(key)
Expand Down
9 changes: 5 additions & 4 deletions core/src/mast/merger/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use core::assert_matches;
use super::*;
use crate::{
Felt, ONE, Word,
advice::AdviceMap,
mast::{
BasicBlockNode, BasicBlockNodeBuilder, CallNodeBuilder, DynNodeBuilder,
ExternalNodeBuilder, LoopNodeBuilder, OpBatch,
Expand Down Expand Up @@ -457,7 +458,7 @@ fn mast_forest_merge_advice_maps_merged() {
Felt::new_unchecked(4),
]);
let value_a = vec![ONE, ONE];
forest_a.advice_map_mut().insert(key_a, value_a.clone());
forest_a = forest_a.with_advice_map(AdviceMap::from_iter([(key_a, value_a.clone())]));

let mut forest_b = MastForest::new();
let id_bar = block_bar().add_to_forest(&mut forest_b).unwrap();
Expand All @@ -470,7 +471,7 @@ fn mast_forest_merge_advice_maps_merged() {
Felt::new_unchecked(1),
]);
let value_b = vec![Felt::new_unchecked(2), Felt::new_unchecked(2)];
forest_b.advice_map_mut().insert(key_b, value_b.clone());
forest_b = forest_b.with_advice_map(AdviceMap::from_iter([(key_b, value_b.clone())]));

let (merged, _root_maps) = MastForest::merge([&forest_a, &forest_b]).unwrap();

Expand All @@ -494,7 +495,7 @@ fn mast_forest_merge_advice_maps_collision() {
Felt::new_unchecked(4),
]);
let value_a = vec![ONE, ONE];
forest_a.advice_map_mut().insert(key_a, value_a);
forest_a = forest_a.with_advice_map(AdviceMap::from_iter([(key_a, value_a)]));

let mut forest_b = MastForest::new();
let id_bar = block_bar().add_to_forest(&mut forest_b).unwrap();
Expand All @@ -503,7 +504,7 @@ fn mast_forest_merge_advice_maps_collision() {
// The key collides with key_a in the forest_a.
let key_b = key_a;
let value_b = vec![Felt::new_unchecked(2), Felt::new_unchecked(2)];
forest_b.advice_map_mut().insert(key_b, value_b);
forest_b = forest_b.with_advice_map(AdviceMap::from_iter([(key_b, value_b)]));

let err = MastForest::merge([&forest_a, &forest_b]).unwrap_err();
assert_matches!(err, MastForestError::AdviceMapKeyCollisionOnMerge(_));
Expand Down
Loading
Loading