-
Notifications
You must be signed in to change notification settings - Fork 138
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve dictionary migration #3318
Conversation
This commit fixes Cadence 1.0 migration when using atree inlined data. See issue: #3288 Previously, MigrateNestedValue() migrates dictionary by using readonly iterator and migrating values in place. This commit migrates keys first using readonly iterator and then migrates values using mutable iterator.
Cadence Benchstat comparisonThis branch with compared with the base branch onflow:master commit 665d604 Collapsed results for better readability
|
Added one last small improvement: c4bed07: Avoid variable shadowing Consistently use |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@turbolent Nice! Thanks for porting #3316 to master and adding mutation checks etc.
I only left a comment to use a different iterator function for cadence v1.0 + atree inlining migration because dictionary.IterateKeys()
in branch feature/atree-register-inlining-v1.0
uses mutable iterators.
Work towards #3288
Info
This PR is a result of investigating and fixing #3288, the broken migration of dictionaries in the atree register inlining version, https://github.com/onflow/cadence/tree/feature/atree-register-inlining-v1.0.
Kudos to @fxamacker for investigating the issue, finding the cause, and coming up with this non-intrusive solution! 👏
This PR mostly just ports #3316 to
master
, so that the atree register inlining feature branch only contains additional changes required for atree register inlining, and the branch does not drift too far off of master.The PR is best reviewed by viewing each commit individually.
Description
02ebd1e: Fix MigrateNestedValue() for dictionary value
The original bug was the use of the read-only iterator when migrating dictionary keys and values. Using the read-only iterator is wrong, as the migration might mutate dictionary keys and values.
However, simply switching from the read-only iterator to the iterator that allows mutations of children is not possible, as the iterator that allows mutations to children does not support reading old dictionary keys that will get a different hash value in Cadence 1.0.
@fxamacker realized that we can split the migration of dictionaries from the current "interleaved" approach of iterating over all key-value pairs, into two phases, one that migrates all keys, and then another that migrates all values.
This was implemented in Fix Cadence 1.0 migration of dictionary values when using atree inlined data #3316, but on top of the atree register inlining feature branch. This PR ports the commit, 02ebd1e, to
master
. Even though the change isn't strictly needed onmaster
, porting it anyways keeps the approach of how dictionaries are migrated the same across the different branches.412780e: Add comments
Explain why the migration of dictionaries is now in two phases.
Also add a note to not attempt to refactor the conflict handling code – I caught myself attempting to "improve" it, just to realize it was working correctly, even after the changes of the previous commit.
274cfce: Refactors the dictionary migration phases into separate functions
The
MigrateNestedValue
function had become very long, so this commit refactors the dictionary case of the switch into two functions. The code got moved as-is and no changes were made to it.76e337c: Adds a test case for migrating dictionaries with enum keys
We did not previously have a test case for it, so add one to ensure this is still supported.
5d2501a: Prevents mutation of dictionary keys
Testnet state migration preview.22 health check after migration error #3288 was hard to debug and fix, because the invalid mutation of child values returned from the read-only mutation did not produce any errors. Only the defensive storage health check after the migration identified there was something wrong.
Improve the migration of nested values by adding assertions that ensure that migrations never mutate dictionary keys. A mutation may replace a dictionary key (e.g. enum with a different enum), but it may never mutate a dictionary key in place (e.g. change the raw value of an enum).
Add a test that has such an invalid migration, and ensure it is immediately rejected.
c4bed07: Avoid variable shadowing
Consistently use
newValue
as the name of the variable that is the migrated version ofexistingValue
, a child values that is being migrated. Avoid shadowing the final result variable of the whole function,migratedValue
.master
branchFiles changed
in the Github PR explorer