Adding more property tests and fixing edge case of dropped operation#936
Conversation
| hex!("516d6911c3b0a36c9227922ca0273a4aee44886201bd186f7ee7e538a769eaa5"), | ||
| hex!("381b24719ff91b13d36cf0dd7622f391f4a461452ed7547a46a992ee4a4025aa"), | ||
| hex!("207793e2ce76c1feb68c7259f883229f985706c8cc2fcf99f481b622a54ba375"), | ||
| hex!("18a457ed03d9d28f8bf84aa05dc3c8005e35564e91d05bf6131094d4f3398528"), |
There was a problem hiding this comment.
this smells like a breaking change?
There was a problem hiding this comment.
Yeah...
Byt as far I understand, this is for the test fixture, in reality this will unlikely produce different root hash.
There was a problem hiding this comment.
Can you explain why the root hashes changed here and would not in production?
There was a problem hiding this comment.
I've mentioned it in PR description. This PR changed how KeyPath is derived from id
Before it has been filling only 16 bytes:
for i in 0..4 {
// max(i) == 3, path[12..][..4]
path[i * 4..][..4].copy_from_slice(&rng.next_u32().to_le_bytes());
}Lines 13 to 24 in 7ef155b
And now it fills all 32 bytes:
nomt/nomt-test-utils/src/lib.rs
Lines 342 to 353 in ed8ad2c
There was a problem hiding this comment.
If we want to play safe, we can do following:
- Merge: Remove unused dependencies and align benchtop #939
- Do a patch release
1.0.3 -> 1.0.4 - Merge this PR
- Do a breaking change release,
1.0.4 -> 1.1.0or even more2.0to be more aligned with semver
There was a problem hiding this comment.
No need for that, I think this is OK. i see now that it's just because the test environment changing.
| .read_write | ||
| .binary_search_by_key(&key_range_end, |x| x.0) | ||
| .unwrap_or_else(|i| i); | ||
| .partition_point(|(key, _)| *key <= key_range_end); |
There was a problem hiding this comment.
i see, if key_range_end is actually in the set of ops we would drop it from the range silently. seems like a good fix.
i will note that this situation would be extremely unlikely to occur with genuinely hashed keys due to the way we shard the key-space among workers, as it essentially requires a hash collision. but good future proofing.
# Conflicts: # nomt/tests/common/mod.rs
Adds the previously-untracked crate the workspace already references — shared quickcheck Arbitrary impls for KeyPath, DivergingPair, SharedPrefixCluster, UniqueSortedKeyPaths and helpers used by the property tests across core and nomt. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
property_post_commit_state_matches_reference reads every key in the expected state, asserts deletes are absent, and compares the Nomt root to nomt_core::update::build_trie computed independently over the same final state — gives an oracle decoupled from Nomt's witness/proof path. property_root_invariant_under_reopen closes the Test instance and re-opens with cleanup_dir=false, asserting the global root is unchanged. Catches drift introduced by sync/flush vs in-memory state. apply_accesses helper deduplicates the read/write/read-then-write dispatch shared by the new tests. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8fc0b1e to
fe6967f
Compare
As follow up of #931
Includes a fix for:
RangeUpdater::newcomputedrange_endwithbinary_search_by_key(...).unwrap_or_else(|i| i).When a key in
read_writeexactly equals the worker'skey_range_end(the max key path of the shard's region), binary_search_by_key returnsOk(i)andunwrap_or_elsereturnsiinstead of the required exclusive endi+1.The matching key is dropped from the worker's range, so the seek is never pushed, no
RootPagePending::SubTrieis emitted, and the second commit's root just inherits the first commit's leaf-root unchanged.Tracing the failing case showed
range_end=0for the second commit (read_write contains onlyKEY_B = [0xFF; 32], andkey_range_end = [0xFF; 32]for the single shard's universe region).Note from @rphmeier
Notable changes
the old account_path filled only bytes 0..16 (
for i in 0..4 { path[i*4..][..4]... }); the new one in nomt-test-utils/src/lib.rs:599-611 uses chunks_exact_mut(4)and fills all 32 bytes. This is the real reason add_remove_1000's expected_roots changed — not a "fixture refresh" but a different key distribution. The new behavior is arguably better (more entropy), but it silently changes any test that depended on the old layout