Two root causes of hash mismatch fixed:
1. Canonical root computation: Hash() now uses BuildInternalTree(skip=0)
over all known stems instead of the page tree's depth-7 internal root.
The page tree is still updated for persistent storage, but the canonical
root bypasses its depth-7 worker split that added extra wrapping levels.
2. Code chunk grouping: UpdateContractCode now matches bintrie's group-based
key derivation exactly — computing the stem key only at group boundaries
and using groupOffset as the suffix, instead of computing a separate
GetBinaryTreeKey per chunk (which produced different stems).
Cross-validation tests (compat_test.go) assert strict equality:
- TestSingleAccountRootMatch
- TestMultiAccountRootMatch
- TestStorageRootMatch
- TestCodeChunkRootMatch
- TestMixedOpsRootMatch
- 4 BuildInternalTree vs bintrie diagnostic tests
48 tests passing, race-detector clean.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>