Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions src/Nethermind/Nethermind.State.Test/StorageProviderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,66 @@ public void Selfdestruct_clears_cache()
provider.Get(nonAccessedStorageCell).ToArray().Should().BeEquivalentTo(StorageTree.ZeroBytes);
}

[Test]
public void Set_empty_value_for_storage_cell_without_read_clears_data()
{
IWorldState worldState = new WorldState(TestTrieStoreFactory.Build(new MemDb(), LimboLogs.Instance), Substitute.For<IDb>(), LogManager);

using var disposable = worldState.BeginScope(IWorldState.PreGenesis);
worldState.CreateAccount(TestItem.AddressA, 1);
worldState.Commit(Prague.Instance);
worldState.CommitTree(0);
Hash256 emptyHash = worldState.StateRoot;

worldState.Set(new StorageCell(TestItem.AddressA, 1), _values[11]);
worldState.Set(new StorageCell(TestItem.AddressA, 2), _values[12]);
worldState.Commit(Prague.Instance);
worldState.CommitTree(1);

var fullHash = worldState.StateRoot;
fullHash.Should().NotBe(emptyHash);

worldState.Set(new StorageCell(TestItem.AddressA, 1), [0]);
worldState.Set(new StorageCell(TestItem.AddressA, 2), [0]);
worldState.Commit(Prague.Instance);
worldState.CommitTree(2);

var clearedHash = worldState.StateRoot;

clearedHash.Should().Be(emptyHash);
}

[Test]
public void Set_empty_value_for_storage_cell_with_read_clears_data()
{
IWorldState worldState = new WorldState(TestTrieStoreFactory.Build(new MemDb(), LimboLogs.Instance), Substitute.For<IDb>(), LogManager);

using var disposable = worldState.BeginScope(IWorldState.PreGenesis);
worldState.CreateAccount(TestItem.AddressA, 1);
worldState.Commit(Prague.Instance);
worldState.CommitTree(0);
Hash256 emptyHash = worldState.StateRoot;

worldState.Set(new StorageCell(TestItem.AddressA, 1), _values[11]);
worldState.Set(new StorageCell(TestItem.AddressA, 2), _values[12]);
worldState.Commit(Prague.Instance);
worldState.CommitTree(1);
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like it will also fail previously if Reset() is called after the commit. Previously the blockchange and the storage tree is separated, now its the same causing the CommitTree to have an implicit reset.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, that's correct. Recreated the same behaviour with calling Reset() - though with calling Reset(false) works fine.


var fullHash = worldState.StateRoot;
fullHash.Should().NotBe(emptyHash);

worldState.Get(new StorageCell(TestItem.AddressA, 1));
worldState.Get(new StorageCell(TestItem.AddressA, 2));
worldState.Set(new StorageCell(TestItem.AddressA, 1), [0]);
worldState.Set(new StorageCell(TestItem.AddressA, 2), [0]);
worldState.Commit(Prague.Instance);
worldState.CommitTree(2);

var clearedHash = worldState.StateRoot;

clearedHash.Should().Be(emptyHash);
}

private class Context
{
public WorldState StateProvider { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,12 @@ public ChangeTrace(byte[]? after)
{
After = after ?? StorageTree.ZeroBytes;
Before = StorageTree.ZeroBytes;
IsInitialValue = true;
}

public byte[] Before;
public byte[] After;
public bool IsInitialValue;
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,8 @@ private byte[] LoadFromTreeStorage(StorageCell storageCell)
foreach (var kvp in BlockChange)
{
byte[] after = kvp.Value.After;
if (!Bytes.AreEqual(kvp.Value.Before, after))
if (!Bytes.AreEqual(kvp.Value.Before, after)
|| kvp.Value.IsInitialValue) // IsInitialValue is so that it does not skip change if it does not know existing value.
{
BlockChange[kvp.Key] = new(after, after);
StorageTree.Set(kvp.Key, after);
Expand Down