Skip to content

Commit

Permalink
Revive IWorldDelta
Browse files Browse the repository at this point in the history
  • Loading branch information
OnedgeLee committed Dec 11, 2023
1 parent 4048596 commit 123fa7c
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 44 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ To be released.
- (Libplanet.Action) Added `IWorld` interface and its implementation.
[[#3462]]
- Added `World` class.
- (Libplanet.Action) Added `IWorldDelta` interface. [[#3462]]
- (Libplanet.Action) Added `IWorldState` interface and its implementation.
[[#3462]]
- Added `WorldBaseState` class.
Expand Down
17 changes: 8 additions & 9 deletions Libplanet.Action/ActionEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -563,8 +563,7 @@ internal IWorld MigrateLegacyStates(IWorld prevWorld, int version)
worldTrie = _stateStore.Commit(worldTrie);
var world = new World(
new WorldBaseState(worldTrie, _stateStore),
ImmutableDictionary<Address, IAccount>.Empty,
prevWorld.BlockDelta);
prevWorld.Delta);
return world;
}

Expand All @@ -574,24 +573,24 @@ private static IWorld CommitLegacyWorld(IWorld prevWorld, IStateStore stateStore
new WorldBaseState(
stateStore.Commit(prevWorld.GetAccount(ReservedAddresses.LegacyAccount).Trie),
stateStore),
ImmutableDictionary<Address, IAccount>.Empty,
prevWorld.BlockDelta);
prevWorld.Delta.CommitAccount(ReservedAddresses.LegacyAccount));
}

private static IWorld CommitWorld(IWorld world, IStateStore stateStore)
private static IWorld CommitWorld(IWorld prevWorld, IStateStore stateStore)
{
var worldTrie = world.Trie;
foreach (var account in world.UncommittedDelta)
var worldTrie = prevWorld.Trie;
var worldDelta = prevWorld.Delta;
foreach (var account in prevWorld.Delta.Uncommitted)
{
var accountTrie = stateStore.Commit(account.Value.Trie);
worldTrie = worldTrie.Set(
ToStateKey(account.Key), new Binary(accountTrie.Hash.ByteArray));
worldDelta = worldDelta.CommitAccount(account.Key);
}

return new World(
new WorldBaseState(stateStore.Commit(worldTrie), stateStore),
ImmutableDictionary<Address, IAccount>.Empty,
world.BlockDelta);
worldDelta);
}

[Pure]
Expand Down
13 changes: 3 additions & 10 deletions Libplanet.Action/State/IWorld.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,11 @@ namespace Libplanet.Action.State
public interface IWorld : IWorldState
{
/// <summary>
/// A dictionary representing cumulative changed account states for each
/// <see cref="Address"/> between blocks.
/// The <see cref="IWorld"/> representing the delta part of
/// this <see cref="IWorld"/>.
/// </summary>
[Pure]
IImmutableDictionary<Address, IAccount> BlockDelta { get; }

/// <summary>
/// A dictionary representing uncommitted changed account states for each
/// <see cref="Address"/>.
/// </summary>
[Pure]
IImmutableDictionary<Address, IAccount> UncommittedDelta { get; }
IWorldDelta Delta { get; }

/// <summary>
/// Gets a new instance that the world state of the given
Expand Down
49 changes: 49 additions & 0 deletions Libplanet.Action/State/IWorldDelta.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System.Collections.Immutable;
using System.Diagnostics.Contracts;
using Libplanet.Crypto;

namespace Libplanet.Action.State
{
public interface IWorldDelta
{
/// <summary>
/// A dictionary representing changed account states for each <see cref="Address"/>.
/// This lasts till new empty delta instance has been made.
/// </summary>
[Pure]
IImmutableDictionary<Address, IAccount> Accounts { get; }

/// <summary>
/// A dictionary representing changed account states for each <see cref="Address"/>.
/// Elements of this collection are removed when <see cref="CommitAccount"/> called
/// by corresponding <see cref="Address"/>.
/// </summary>
[Pure]
IImmutableDictionary<Address, IAccount> Uncommitted { get; }

/// <summary>
/// Set account on both of <see cref="Accounts"/> and <see cref="Uncommitted"/>
/// dictionaries. If <see cref="IAccount"/> already exists on
/// <paramref name="address"/>, update with new <paramref name="account"/>.
/// </summary>
/// <param name="address"><see cref="Address"/> to set on.</param>
/// <param name="account"><see cref="IAccount"/> to set.</param>
/// <returns>New <see cref="IWorldDelta"/> that account is properly set.</returns>
[Pure]
IWorldDelta SetAccount(Address address, IAccount account);

/// <summary>
/// Remove item from <see cref="Uncommitted"/> dictionary where its key is
/// <paramref name="address"/>.
/// </summary>
/// <param name="address"><see cref="Address"/> of <see cref="IAccount"/> to
/// remove from <see cref="Uncommitted"/>.</param>
/// <returns>
/// New <see cref="IWorldDelta"/> item of <paramref name="address"/> removed from
/// <see cref="Uncommitted"/>.
/// If corresponding uncommitted does not exist, returns identical one.
/// </returns>
[Pure]
IWorldDelta CommitAccount(Address address);
}
}
29 changes: 7 additions & 22 deletions Libplanet.Action/State/World.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.Collections.Immutable;
using System.Diagnostics.Contracts;
using Libplanet.Crypto;
using Libplanet.Store.Trie;
Expand All @@ -14,34 +13,21 @@ public class World : IWorld
private readonly IWorldState _baseState;

public World(IWorldState baseState)
: this(baseState, ImmutableDictionary<Address, IAccount>.Empty)
: this(baseState, new WorldDelta())
{
}

public World(
IWorldState baseState,
IImmutableDictionary<Address, IAccount> uncommittedDelta)
: this(
baseState,
uncommittedDelta,
ImmutableDictionary<Address, IAccount>.Empty)
{
}

public World(
IWorldState baseState,
IImmutableDictionary<Address, IAccount> uncommittedDelta,
IImmutableDictionary<Address, IAccount> blockDelta)
IWorldDelta delta)
{
_baseState = baseState;
UncommittedDelta = uncommittedDelta;
BlockDelta = blockDelta;
Delta = delta;
Legacy = baseState.Legacy;
}

public IImmutableDictionary<Address, IAccount> BlockDelta { get; }

public IImmutableDictionary<Address, IAccount> UncommittedDelta { get; }
/// <inheritdoc/>
public IWorldDelta Delta { get; }

/// <inheritdoc/>
[Pure]
Expand All @@ -55,7 +41,7 @@ public World(
[Pure]
public IAccount GetAccount(Address address)
{
return BlockDelta.TryGetValue(address, out IAccount? account)
return Delta.Accounts.TryGetValue(address, out IAccount? account)
? account
: _baseState.GetAccount(address);
}
Expand All @@ -72,8 +58,7 @@ public IWorld SetAccount(Address address, IAccount account)

return new World(
this,
UncommittedDelta.SetItem(address, account),
BlockDelta.SetItem(address, account));
Delta.SetAccount(address, account));
}
}
}
56 changes: 56 additions & 0 deletions Libplanet.Action/State/WorldDelta.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using System.Collections.Immutable;
using System.Linq;
using Libplanet.Crypto;

namespace Libplanet.Action.State
{
public class WorldDelta : IWorldDelta
{
private IImmutableDictionary<Address, AccountItem> _accounts;

public WorldDelta()
{
_accounts = ImmutableDictionary<Address, AccountItem>.Empty;
}

private WorldDelta(IImmutableDictionary<Address, AccountItem> accounts)
{
_accounts = accounts;
}

/// <inheritdoc cref="IWorldDelta.Accounts"/>
public IImmutableDictionary<Address, IAccount> Accounts
=> _accounts
.ToImmutableDictionary(item => item.Key, item => item.Value.Account);

/// <inheritdoc cref="IWorldDelta.Uncommitted"/>
public IImmutableDictionary<Address, IAccount> Uncommitted
=> _accounts
.Where(item => !item.Value.Committed)
.ToImmutableDictionary(item => item.Key, item => item.Value.Account);

/// <inheritdoc cref="IWorldDelta.SetAccount"/>
public IWorldDelta SetAccount(Address address, IAccount account)
=> new WorldDelta(_accounts.SetItem(address, new AccountItem(account, false)));

/// <inheritdoc cref="IWorldDelta.CommitAccount"/>
public IWorldDelta CommitAccount(Address address)
=> _accounts.TryGetValue(address, out AccountItem accountItem)
? new WorldDelta(
_accounts.SetItem(address, new AccountItem(accountItem.Account, true)))
: this;

internal struct AccountItem
{
public AccountItem(IAccount account, bool committed)
{
Account = account;
Committed = committed;
}

public IAccount Account { get; }

public bool Committed { get; set; }
}
}
}
4 changes: 1 addition & 3 deletions Libplanet.Explorer.Tests/Queries/StateQueryTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -461,9 +461,7 @@ public MockWorld()

public bool Legacy => true;

public IImmutableDictionary<Address, IAccount> BlockDelta => throw new System.NotImplementedException();

public IImmutableDictionary<Address, IAccount> UncommittedDelta => throw new System.NotImplementedException();
public IWorldDelta Delta => throw new System.NotImplementedException();

public IAccount GetAccount(Address address)
=> new MockAccount();
Expand Down

0 comments on commit 123fa7c

Please sign in to comment.