Skip to content

Commit

Permalink
Merge pull request #3598 from greymistcube/refactor/worldstate
Browse files Browse the repository at this point in the history
♻️ Refactor `IWorldState` to be read-only
  • Loading branch information
greymistcube authored Jan 10, 2024
2 parents 73c9b98 + 9d5838b commit 87492af
Show file tree
Hide file tree
Showing 26 changed files with 454 additions and 270 deletions.
9 changes: 9 additions & 0 deletions Libplanet.Action.Tests/Mocks/MockWorldState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ public IAccount GetAccount(Address address)
? new HashDigest<SHA256>(stateRootNotNull)
: null));

public IAccountState GetAccountState(Address address)
=> Legacy && address.Equals(ReservedAddresses.LegacyAccount)
? new MockAccountState(_stateStore, Trie.Hash)
: new MockAccountState(
_stateStore,
Trie.Get(ToStateKey(address)) is { } stateRootNotNull
? new HashDigest<SHA256>(stateRootNotNull)
: null);

public IWorldState SetAccountState(Address address, IAccount account)
=> Legacy && address.Equals(ReservedAddresses.LegacyAccount)
? new MockWorldState(_stateStore, account.Trie.Hash)
Expand Down
1 change: 0 additions & 1 deletion Libplanet.Action/State/AccountState.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Bencodex.Types;
Expand Down
1 change: 0 additions & 1 deletion Libplanet.Action/State/IAccountState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using Libplanet.Crypto;
using Libplanet.Store.Trie;
using Libplanet.Types.Assets;
using Libplanet.Types.Blocks;
using Libplanet.Types.Consensus;

namespace Libplanet.Action.State
Expand Down
12 changes: 11 additions & 1 deletion Libplanet.Action/State/IWorld.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.Contracts;
using Libplanet.Crypto;

Expand Down Expand Up @@ -42,6 +41,17 @@ public interface IWorld : IWorldState
[Pure]
IWorldDelta Delta { get; }

/// <summary>
/// Gets the <see cref="IAccount"/> of the given <paramref name="address"/>.
/// </summary>
/// <param name="address">The <see cref="Address"/> referring
/// the world to get its state.</param>
/// <returns>The <see cref="IAccount"/> of the given <paramref name="address"/>.
/// If it has never been set to any state it returns <see langword="null"/>
/// instead.</returns>
[Pure]
IAccount GetAccount(Address address);

/// <summary>
/// Gets a new instance that the world state of the given
/// <paramref name="address"/> is set to the given
Expand Down
6 changes: 3 additions & 3 deletions Libplanet.Action/State/IWorldState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@ public interface IWorldState
bool Legacy { get; }

/// <summary>
/// Gets the <see cref="IAccount"/> of the given <paramref name="address"/>.
/// Gets the <see cref="IAccountState"/> of the given <paramref name="address"/>.
/// </summary>
/// <param name="address">The <see cref="Address"/> referring
/// the world to get its state.</param>
/// <returns>The <see cref="Account"/> of the given <paramref name="address"/>.
/// <returns>The <see cref="IAccountState"/> of the given <paramref name="address"/>.
/// If it has never been set to any state it returns <see langword="null"/>
/// instead.</returns>
[Pure]
IAccount GetAccount(Address address);
IAccountState GetAccountState(Address address);
}
}
10 changes: 7 additions & 3 deletions Libplanet.Action/State/World.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,23 @@ public World(
[Pure]
public ITrie Trie => _baseState.Trie;

/// <inheritdoc/>
/// <inheritdoc cref="IWorldState.Legacy/>
[Pure]
public bool Legacy { get; private set; }

/// <inheritdoc/>
/// <inheritdoc cref="IWorld.GetAccount"/>
[Pure]
public IAccount GetAccount(Address address)
{
return Delta.Accounts.TryGetValue(address, out IAccount? account)
? account
: _baseState.GetAccount(address);
: new Account(_baseState.GetAccountState(address));
}

/// <inheritdoc cref="IWorld.GetAccountState"/>
[Pure]
public IAccountState GetAccountState(Address address) => GetAccount(address);

/// <inheritdoc/>
[Pure]
public IWorld SetAccount(Address address, IAccount account)
Expand Down
14 changes: 8 additions & 6 deletions Libplanet.Action/State/WorldBaseState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,22 @@ public WorldBaseState(ITrie trie, IStateStore stateStore)
public bool Legacy { get; private set; }

/// <inheritdoc cref="IWorldState.GetAccount"/>
public IAccount GetAccount(Address address)
public IAccount GetAccount(Address address) => new Account(GetAccountState(address));

public IAccountState GetAccountState(Address address)
{
if (Legacy)
{
return address.Equals(ReservedAddresses.LegacyAccount)
? new Account(new AccountState(Trie))
: new Account(new AccountState(_stateStore.GetStateRoot(null)));
? new AccountState(Trie)
: new AccountState(_stateStore.GetStateRoot(null));
}
else
{
return Trie.Get(ToStateKey(address)) is Binary accountStateRootHash
? new Account(new AccountState(_stateStore.GetStateRoot(
new HashDigest<SHA256>(accountStateRootHash.ByteArray))))
: new Account(new AccountState(_stateStore.GetStateRoot(null)));
? new AccountState(_stateStore.GetStateRoot(
new HashDigest<SHA256>(accountStateRootHash.ByteArray)))
: new AccountState(_stateStore.GetStateRoot(null));
}
}
}
Expand Down
8 changes: 2 additions & 6 deletions Libplanet.Action/State/WorldExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
using System.Collections.Immutable;
using Bencodex.Types;
using Libplanet.Crypto;

namespace Libplanet.Action.State
{
internal static class WorldExtensions
{
internal static IAccount GetFungibleAssetsAccount(this IWorldState world) =>
internal static IAccount GetFungibleAssetsAccount(this IWorld world) =>
world.GetAccount(ReservedAddresses.LegacyAccount);

internal static IAccount GetValidatorSetAccount(this IWorldState world) =>
internal static IAccount GetValidatorSetAccount(this IWorld world) =>
world.GetAccount(ReservedAddresses.LegacyAccount);

internal static IWorld SetFungibleAssetsAccount(
Expand Down
66 changes: 17 additions & 49 deletions Libplanet.Explorer.Tests/Queries/StateQueryTest.Mocks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System.Numerics;
using System.Security.Cryptography;
using Bencodex.Types;
using Libplanet.Action;
using Libplanet.Action.State;
using Libplanet.Common;
using Libplanet.Crypto;
Expand Down Expand Up @@ -38,44 +37,44 @@ private class MockChainStates : IBlockChainStates
: null;

public IWorldState GetWorldState(HashDigest<SHA256>? stateRootHash) =>
new MockWorld(stateRootHash);
new MockWorldState(stateRootHash);

public IWorldState GetWorldState(BlockHash? blockHash) =>
new MockWorld(ToStateRootHash(blockHash));
new MockWorldState(ToStateRootHash(blockHash));

public IValue GetState(HashDigest<SHA256>? stateRootHash, Address address) =>
new MockAccount(stateRootHash).GetState(address);
new MockAccountState(stateRootHash).GetState(address);

public IValue GetState(BlockHash? blockHash, Address address) =>
new MockAccount(ToStateRootHash(blockHash)).GetState(address);
new MockAccountState(ToStateRootHash(blockHash)).GetState(address);

public FungibleAssetValue GetBalance(
HashDigest<SHA256>? stateRootHash, Address address, Currency currency) =>
new MockAccount(stateRootHash).GetBalance(address, currency);
new MockAccountState(stateRootHash).GetBalance(address, currency);

public FungibleAssetValue GetBalance(
BlockHash? blockHash, Address address, Currency currency) =>
new MockAccount(ToStateRootHash(blockHash)).GetBalance(address, currency);
new MockAccountState(ToStateRootHash(blockHash)).GetBalance(address, currency);

public FungibleAssetValue GetTotalSupply(HashDigest<SHA256>? stateRootHash, Currency currency) =>
new MockAccount(stateRootHash).GetTotalSupply(currency);
new MockAccountState(stateRootHash).GetTotalSupply(currency);

public FungibleAssetValue GetTotalSupply(BlockHash? blockHash, Currency currency) =>
new MockAccount(ToStateRootHash(blockHash)).GetTotalSupply(currency);
new MockAccountState(ToStateRootHash(blockHash)).GetTotalSupply(currency);

public ValidatorSet GetValidatorSet(HashDigest<SHA256>? stateRootHash) =>
new MockAccount(stateRootHash).GetValidatorSet();
new MockAccountState(stateRootHash).GetValidatorSet();

public ValidatorSet GetValidatorSet(BlockHash? blockHash) =>
new MockAccount(ToStateRootHash(blockHash)).GetValidatorSet();
new MockAccountState(ToStateRootHash(blockHash)).GetValidatorSet();
}

// Behaves like a non-empty world only if state root hash is non-null.
private class MockWorld : IWorld
private class MockWorldState : IWorldState
{
private readonly HashDigest<SHA256>? _stateRootHash;

public MockWorld(HashDigest<SHA256>? stateRootHash)
public MockWorldState(HashDigest<SHA256>? stateRootHash)
{
_stateRootHash = stateRootHash;
}
Expand All @@ -86,26 +85,21 @@ public MockWorld(HashDigest<SHA256>? stateRootHash)

public IWorldDelta Delta => throw new System.NotImplementedException();

// Only returns a non-empty account if state root hash is not null and
// address is legacy account address
public IAccount GetAccount(Address address) =>
public IAccountState GetAccountState(Address address) =>
_stateRootHash is { } && ReservedAddresses.LegacyAccount.Equals(address)
? new MockAccount(_stateRootHash)
: new MockAccount(null);

public IWorld SetAccount(Address address, IAccount account) =>
throw new System.NotImplementedException();
? new MockAccountState(_stateRootHash)
: new MockAccountState(null);
}

// Behaves like a non-empty account only if state root hash is non-null.
private class MockAccount : IAccount
private class MockAccountState : IAccountState
{
public static readonly Address Address =
new Address("0x5003712B63baAB98094aD678EA2B24BcE445D076");

private readonly HashDigest<SHA256>? _stateRootHash;

public MockAccount(HashDigest<SHA256>? stateRootHash)
public MockAccountState(HashDigest<SHA256>? stateRootHash)
{
_stateRootHash = stateRootHash;
}
Expand Down Expand Up @@ -141,32 +135,6 @@ public ValidatorSet GetValidatorSet() =>
"032038e153d344773986c039ba5dbff12ae70cfdf6ea8beb7c5ea9b361a72a9233"),
new BigInteger(1)),
});

public IAccount SetState(Address address, IValue state) =>
throw new System.NotImplementedException();

public IAccount RemoveState(Address address) =>
throw new System.NotImplementedException();

public IAccount MintAsset(
IActionContext context,
Address recipient,
FungibleAssetValue value) => throw new System.NotImplementedException();

public IAccount TransferAsset(
IActionContext context,
Address sender,
Address recipient,
FungibleAssetValue value,
bool allowNegativeBalance = false) => throw new System.NotImplementedException();

public IAccount BurnAsset(
IActionContext context,
Address owner,
FungibleAssetValue value) => throw new System.NotImplementedException();

public IAccount SetValidator(Validator validator) =>
throw new System.NotImplementedException();
}

private class MockTrie : ITrie
Expand Down
4 changes: 2 additions & 2 deletions Libplanet.Explorer/GraphTypes/WorldStateType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public WorldStateType()
}
),
resolve: context =>
context.Source.GetAccount(context.GetArgument<Address>("address"))
context.Source.GetAccountState(context.GetArgument<Address>("address"))
);

Field<NonNullGraphType<ListGraphType<NonNullGraphType<AccountStateType>>>>(
Expand All @@ -54,7 +54,7 @@ public WorldStateType()
),
resolve: context => context
.GetArgument<Address[]>("addresses")
.Select(address => context.Source.GetAccount(address))
.Select(address => context.Source.GetAccountState(address))
.ToArray()
);
}
Expand Down
16 changes: 8 additions & 8 deletions Libplanet.Explorer/Queries/StateQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,14 @@ private static object ResolveWorldState(IResolveFieldContext<IBlockChainStates>
{
return context.Source
.GetWorldState(offsetBlockHash)
.GetAccount(ReservedAddresses.LegacyAccount)
.GetAccountState(ReservedAddresses.LegacyAccount)
.GetStates(addresses);
}

case (_, srh: not null):
return context.Source
.GetWorldState(offsetStateRootHash)
.GetAccount(ReservedAddresses.LegacyAccount)
.GetAccountState(ReservedAddresses.LegacyAccount)
.GetStates(addresses);
}
}
Expand All @@ -146,14 +146,14 @@ private static object ResolveBalance(IResolveFieldContext<IBlockChainStates> con
{
return context.Source
.GetWorldState(offsetBlockHash)
.GetAccount(ReservedAddresses.LegacyAccount)
.GetAccountState(ReservedAddresses.LegacyAccount)
.GetBalance(owner, currency);
}

case (_, srh: not null):
return context.Source
.GetWorldState(offsetStateRootHash)
.GetAccount(ReservedAddresses.LegacyAccount)
.GetAccountState(ReservedAddresses.LegacyAccount)
.GetBalance(owner, currency);
}
}
Expand Down Expand Up @@ -187,12 +187,12 @@ private static object ResolveBalance(IResolveFieldContext<IBlockChainStates> con
case (blockhash: not null, _):
return context.Source
.GetWorldState(offsetBlockHash)
.GetAccount(ReservedAddresses.LegacyAccount)
.GetAccountState(ReservedAddresses.LegacyAccount)
.GetTotalSupply(currency);
case (_, srh: not null):
return context.Source
.GetWorldState(offsetStateRootHash)
.GetAccount(ReservedAddresses.LegacyAccount)
.GetAccountState(ReservedAddresses.LegacyAccount)
.GetTotalSupply(currency);
}
}
Expand All @@ -216,12 +216,12 @@ private static object ResolveBalance(IResolveFieldContext<IBlockChainStates> con
case (blockhash: not null, _):
return context.Source
.GetWorldState(offsetBlockHash)
.GetAccount(ReservedAddresses.LegacyAccount)
.GetAccountState(ReservedAddresses.LegacyAccount)
.GetValidatorSet().Validators;
case (_, srh: not null):
return context.Source
.GetWorldState(offsetStateRootHash)
.GetAccount(ReservedAddresses.LegacyAccount)
.GetAccountState(ReservedAddresses.LegacyAccount)
.GetValidatorSet().Validators;
}
}
Expand Down
2 changes: 1 addition & 1 deletion Libplanet.Net.Tests/Consensus/ContextTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ void BroadcastMessage(ConsensusMsg message) =>
TestUtils.PrivateKeys[0],
blockChain
.GetWorldState(blockChain[0L].Hash)
.GetAccount(ReservedAddresses.LegacyAccount)
.GetAccountState(ReservedAddresses.LegacyAccount)
.GetValidatorSet(),
contextTimeoutOptions: new ContextTimeoutOption());

Expand Down
Loading

0 comments on commit 87492af

Please sign in to comment.