Skip to content

Conversation

@phrwlk
Copy link
Contributor

@phrwlk phrwlk commented Nov 15, 2025

Describe your changes

SmtLeaf::new_multiple() previously accepted entries in arbitrary order and allowed duplicate keys, which violated the documented invariant that SmtLeaf::Multiple must be canonicalized by key order and contain unique keys. This inconsistency could corrupt downstream behavior in several places: SmtLeaf::insert() and remove() rely on binary_search over a sorted vector; SmtLeaf::hash() depends on canonical order while the specification requires hashing entries ordered by key; and deserialization admitted unsorted or duplicate entries, which could then be inserted into a PartialSmt and later produce incorrect updates. To fix this, new_multiple() now sorts entries by cmp_keys() and rejects duplicate keys after enforcing that all keys map to the same leaf index and the count is within MAX_LEAF_ENTRIES. A new error DuplicateKeysInMultipleLeaf has been added for this case. Tests were added to validate canonical sorting and hash stability, duplicate-key rejection, and that deserialization canonicalizes order while rejecting duplicate keys.

Copy link
Contributor

@huitseeker huitseeker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SmtLeaf::new_multiple() previously accepted entries in arbitrary order and allowed duplicate keys, which violated the documented invariant that SmtLeaf::Multiple must be canonicalized by key order and contain unique keys.

I missed that documentation, where is it?

Is this a behavior change, or fixing an inconsistency?

Comment on lines +113 to +120
let mut entries = entries;
entries.sort_by(|(key_1, _), (key_2, _)| cmp_keys(*key_1, *key_2));

for pair in entries.windows(2) {
if pair[0].0 == pair[1].0 {
return Err(SmtLeafError::DuplicateKeysInMultipleLeaf { key: pair[0].0 });
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These checks are currently done in pairs_to_leaf() function an din the insert() function. It may still make sense to move the checks here (to check these invariants during deserialization) - but then we should make sure we remove the no longer needed code these function.

@phrwlk
Copy link
Contributor Author

phrwlk commented Nov 23, 2025

SmtLeaf::new_multiple() previously accepted entries in arbitrary order and allowed duplicate keys, which violated the documented invariant that SmtLeaf::Multiple must be canonicalized by key order and contain unique keys.

I missed that documentation, where is it?

Is this a behavior change, or fixing an inconsistency?

Fixing an inconsistency.
pairs_to_leaf() enforced the invariant, but new_multiple() didn't.

@phrwlk
Copy link
Contributor Author

phrwlk commented Nov 23, 2025

SmtLeaf::new_multiple() previously accepted entries in arbitrary order and allowed duplicate keys, which violated the documented invariant that SmtLeaf::Multiple must be canonicalized by key order and contain unique keys.

I missed that documentation, where is it?

Is this a behavior change, or fixing an inconsistency?

I missed that documentation, where is it? - Yes, i was wrong in my description, i should've said "which violated the implicit invariant that SmtLeaf::Multiple must be canonicalized by key order and contain unique keys"
But also I can add documentation for SmtLeaf::Multiple

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants