Skip to content
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

Fix/snap sync edge cases #7708

Merged
merged 9 commits into from
Nov 5, 2024
Merged

Fix/snap sync edge cases #7708

merged 9 commits into from
Nov 5, 2024

Conversation

asdacap
Copy link
Contributor

@asdacap asdacap commented Nov 4, 2024

  • Allow increasing partition count above 256, up to int.MaxValue. This is mainly useful for triggering edge case.
  • Collect, and add edge case to unit test and fix them.
  • Fix storage get requested twice between partition boundary.
  • Fix storage may get persisted twice between partition boundary.
  • Fix the same two above issue between address range (the first and last key always overlap).
  • Switch boundary logic to use TreePath instead of array.

Types of changes

What types of changes does your code introduce?

  • Bugfix (a non-breaking change that fixes an issue)

Testing

Requires testing

  • Yes
  • No

If yes, did you write tests?

  • Yes
  • No

Notes on testing

  • Testing...

@asdacap asdacap marked this pull request as ready for review November 4, 2024 11:38
Copy link
Member

@LukaszRozmej LukaszRozmej left a comment

Choose a reason for hiding this comment

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

Need @damian-orzechowski to take a look

Comment on lines +76 to +77
if (accountRangePartitionCount < 1 || accountRangePartitionCount > int.MaxValue)
throw new ArgumentException($"Account range partition must be between 1 to {int.MaxValue}.");
Copy link
Member

Choose a reason for hiding this comment

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

this if now doesn't make sense, basically you need to check if accountRangePartitionCount > 0 (but maybe you can assume then it is 1? Or maybe change accountRangePartitionCount to be uint?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

True, its useless now.

Comment on lines 95 to +96
Hash256 startingPath = new Hash256(Keccak.Zero.Bytes);
startingPath.Bytes[0] = curStartingPath;
BinaryPrimitives.WriteUInt32BigEndian(startingPath.Bytes, curStartingPath);
Copy link
Member

Choose a reason for hiding this comment

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

why not write directly to partition.NextAccountPath and not create Hash256 at all?

@@ -112,7 +110,7 @@ private void SetupAccountRangePartition()
else
{
limitPath = new Hash256(Keccak.Zero.Bytes);
limitPath.Bytes[0] = curStartingPath;
BinaryPrimitives.WriteUInt32BigEndian(limitPath.Bytes, curStartingPath);
Copy link
Member

Choose a reason for hiding this comment

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

same here

Comment on lines +85 to +101
// The server will always give one node extra after limitpath if it can fit in the response.
// When we have extra storage, the extra storage must not be re-stored as it may have already been set
// by another top level partition. If the sync pivot moved and the storage was modified, it must not be saved
// here along with updated ancestor so that healing can detect that the storage need to be healed.
//
// Unfortunately, without introducing large change to the tree, the easiest way to
// exclude the extra storage is to just rebuild the whole tree and also skip stitching.
// Fortunately, this should only happen n-1 time where n is the number of top level
// partition count.

tree.RootHash = Keccak.EmptyTreeHash;
for (var index = 0; index < accounts.Count; index++)
{
PathWithAccount account = accounts[index];
if (account.Path >= limitHash || account.Path < startingHash) continue;
_ = tree.Set(account.Path, account.Account);
}
Copy link
Member

Choose a reason for hiding this comment

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

Can we just detect and ignore that one extra node, instead of rebuilding the whole tree? Otherwise partitioning storage tree's is useless?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Its not just the node, but the parents that touches the node also. Partitionning is not useless, this only happens 16 time on mainnet.

Copy link
Contributor

Choose a reason for hiding this comment

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

Probably a super minor optimisation, but could check hasExtraStorage in the 1st loop and not make changes to the tree, if we will still will rebuild it.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also - if we skip the extra node, why then skip stitching as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The first loop is needed to verify the hash. Not sure aboutt stitching...

Comment on lines +215 to +216
proofNodesToProcess.Push((child, childPath));
sortedBoundaryList.Add((child, childPath));
Copy link
Member

Choose a reason for hiding this comment

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

out of scope of this PR: but I always was curious if we can use some memory pooling on snap syncing

src/Nethermind/Nethermind.Core/Crypto/Hash256.cs Outdated Show resolved Hide resolved
src/Nethermind/Nethermind.Core/Crypto/Hash256.cs Outdated Show resolved Hide resolved
@asdacap asdacap merged commit 72b3ee7 into master Nov 5, 2024
77 checks passed
@asdacap asdacap deleted the fix/snap-sync-edge-cases branch November 5, 2024 07:52
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.

5 participants