/
IAccountStateDelta.cs
98 lines (94 loc) · 3.9 KB
/
IAccountStateDelta.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.Contracts;
using System.Linq;
using Bencodex.Types;
namespace Libplanet.Action
{
/// <summary>
/// An interface to manipulate account states with
/// maintaining the set of <see cref="UpdatedAddresses"/>.
/// <para>It is like a map which is virtually initialized such
/// that every possible <see cref="Address"/> exists and
/// is mapped to <c>null</c>. That means that:</para>
/// <list type="bullet">
/// <item>
/// <description>it does not have length,</description>
/// </item>
/// <item>
/// <description>its index getter never throws
/// <see cref="KeyNotFoundException"/>,
/// but returns <c>null</c> instead, and</description>
/// </item>
/// <item>
/// <description>filling an <see cref="Address"/> with
/// <c>null</c> state cannot be distinguished from
/// the <see cref="Address"/> having never been set to
/// any state.</description>
/// </item>
/// </list>
/// </summary>
/// <remarks>
/// This interface is immutable. <see cref="SetState(Address, IValue)"/>
/// method does not manipulate the instance, but returns a new
/// <see cref="IAccountStateDelta"/> instance with updated states.
/// </remarks>
public interface IAccountStateDelta
{
/// <summary>
/// <seealso cref="Address"/>es of the accounts that have
/// been updated since then.
/// </summary>
[Pure]
IImmutableSet<Address> UpdatedAddresses { get; }
/// <summary>
/// Gets the account state of the given <paramref name="address"/>.
/// </summary>
/// <param name="address">The <see cref="Address"/> referring
/// the account to get its state.</param>
/// <returns>The account state of the given <paramref name="address"/>.
/// If it has never been set to any state it returns <c>null</c>
/// instead.</returns>
[Pure]
IValue GetState(Address address);
/// <summary>
/// Gets a new instance that the account state of the given
/// <paramref name="address"/> is set to the given
/// <paramref name="state"/>.
/// </summary>
/// <param name="address">The <see cref="Address"/> referring
/// the account to set its state.</param>
/// <param name="state">The new state to fill the account with.</param>
/// <returns>A new <see cref="IAccountStateDelta"/> instance that
/// the account state of the given <paramref name="address"/>
/// is set to the given <paramref name="state"/>.</returns>
/// <remarks>
/// This method method does not manipulate the instance,
/// but returns a new <see cref="IAccountStateDelta"/> instance
/// with updated states instead.
/// </remarks>
[Pure]
IAccountStateDelta SetState(Address address, IValue state);
}
internal static class AccountStateDeltaExtensions
{
// TODO: This method should be a part of IAccountStateDelta interface
// and the current implementation should be its default implementation
// (when C# 8 comes out). Although the current implementation is
// an only way using only generic methods/properties that
// the IAccountStateDelta interface exposes, it is quite inefficient
// when an implementing class maintains their own dirty dictionary.
// (See also AccountStateDeltaImpl.UpdatedStates field.)
public static IImmutableDictionary<Address, IValue> GetUpdatedStates(
this IAccountStateDelta delta
)
{
return delta.UpdatedAddresses.Select(address =>
new KeyValuePair<Address, IValue>(
address,
delta.GetState(address)
)
).ToImmutableDictionary();
}
}
}