Skip to content

Commit e244608

Browse files
committed
Added direct commit of world to IStateStore
1 parent 3eec515 commit e244608

File tree

2 files changed

+106
-1
lines changed

2 files changed

+106
-1
lines changed

src/Libplanet.Action/AssemblyInfo.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Runtime.CompilerServices;
22

3-
[assembly: InternalsVisibleTo("Libplanet.Tests")]
3+
[assembly: InternalsVisibleTo("Libplanet")]
44
[assembly: InternalsVisibleTo("Libplanet.Action.Tests")]
55
[assembly: InternalsVisibleTo("Libplanet.Explorer.Tests")]
66
[assembly: InternalsVisibleTo("Libplanet.Mocks")]
7+
[assembly: InternalsVisibleTo("Libplanet.Tests")]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Security.Cryptography;
5+
using Bencodex.Types;
6+
using Libplanet.Action.State;
7+
using Libplanet.Common;
8+
using Libplanet.Crypto;
9+
using Libplanet.Store.Trie;
10+
using Libplanet.Types.Blocks;
11+
12+
namespace Libplanet.Store
13+
{
14+
/// <summary>
15+
/// Convenient extension methods for <see cref="IStateStore"/>.
16+
/// </summary>
17+
public static class IStateStoreExtensions
18+
{
19+
/// <summary>
20+
/// Commits <paramref name="data"/> representing a world state directly
21+
/// to <see cref="IStateStore"/> and returns its state root hash.
22+
/// The world state created is set to <see cref="BlockMetadata.CurrentProtocolVersion"/>.
23+
/// </summary>
24+
/// <param name="stateStore">The <see cref="IStateStore"/> to commit to.</param>
25+
/// <param name="data">The data representing a world state to commit.</param>
26+
/// <returns>The state root hash of the <paramref name="data"/> committed.</returns>
27+
/// <exception cref="ArgumentException">Thrown if given <paramref name="data"/>
28+
/// is not in the right format.
29+
/// <list type="bullet">
30+
/// <item><description>
31+
/// Every key in <paramref name="data"/> must be a <see cref="Binary"/> of length
32+
/// <see cref="Address.Size"/>.
33+
/// </description></item>
34+
/// <item><description>
35+
/// Every value in <paramref name="data"/> must be a <see cref="Dictionary"/> with
36+
/// each key in the <see cref="Dictionary"/> being a <see cref="Binary"/> of length
37+
/// <see cref="Address.Size"/>.
38+
/// </description></item>
39+
/// </list>
40+
/// </exception>
41+
public static HashDigest<SHA256> CommitWorld(
42+
this IStateStore stateStore,
43+
Dictionary data)
44+
{
45+
try
46+
{
47+
var dictionary = data.ToDictionary(
48+
outerPair => new Address(((Binary)outerPair.Key).ByteArray),
49+
outerPair => ((Dictionary)outerPair.Value).ToDictionary(
50+
innerPair => new Address(((Binary)innerPair.Key).ByteArray),
51+
innerPair => innerPair.Value));
52+
return stateStore.CommitWorld(dictionary);
53+
}
54+
catch (Exception e)
55+
{
56+
throw new ArgumentException(
57+
$"Could not convert {nameof(data)} to a proper format",
58+
nameof(data),
59+
e);
60+
}
61+
}
62+
63+
/// <summary>
64+
/// Commits <paramref name="data"/> representing a world state directly
65+
/// to <see cref="IStateStore"/> and returns its state root hash.
66+
/// The world state created is set to <see cref="BlockMetadata.CurrentProtocolVersion"/>.
67+
/// </summary>
68+
/// <param name="stateStore">The <see cref="IStateStore"/> to commit to.</param>
69+
/// <param name="data">The data representing a world state to commit.</param>
70+
/// <returns>The state root hash of the <paramref name="data"/> committed.</returns>
71+
public static HashDigest<SHA256> CommitWorld(
72+
this IStateStore stateStore,
73+
Dictionary<Address, Dictionary<Address, IValue>> data)
74+
{
75+
var stateRoot = stateStore.GetStateRoot(null);
76+
stateRoot = stateRoot.SetMetadata(
77+
new TrieMetadata(BlockMetadata.CurrentProtocolVersion));
78+
stateRoot = stateStore.Commit(stateRoot);
79+
foreach ((var key, var value) in data)
80+
{
81+
stateRoot = stateRoot.Set(
82+
KeyConverters.ToStateKey(key),
83+
new Binary(stateStore.CommitAccount(value).ByteArray));
84+
}
85+
86+
return stateStore.Commit(stateRoot).Hash;
87+
}
88+
89+
private static HashDigest<SHA256> CommitAccount(
90+
this IStateStore stateStore,
91+
Dictionary<Address, IValue> data)
92+
{
93+
var stateRoot = stateStore.GetStateRoot(null);
94+
foreach((var key, var value) in data)
95+
{
96+
stateRoot = stateRoot.Set(
97+
KeyConverters.ToStateKey(key),
98+
value);
99+
}
100+
101+
return stateStore.Commit(stateRoot).Hash;
102+
}
103+
}
104+
}

0 commit comments

Comments
 (0)