1
|
|
using System;
|
2
|
|
using System.Collections.Immutable;
|
3
|
|
using System.Linq;
|
4
|
|
using Bencodex.Types;
|
5
|
|
using Libplanet.Action;
|
6
|
|
using Libplanet.Assets;
|
7
|
|
using Libplanet.Store.Trie;
|
8
|
|
using Libplanet.Tests.Store.Trie;
|
9
|
|
using Xunit;
|
10
|
|
|
11
|
|
namespace Libplanet.Tests.Action
|
12
|
|
{
|
13
|
|
public class ActionContextTest
|
14
|
|
{
|
15
|
|
[Fact]
|
16
|
|
public void RandomShouldBeDeterministic()
|
17
|
1
|
{
|
18
|
1
|
(int Seed, int Expected)[] testCases =
|
19
|
1
|
{
|
20
|
1
|
(0, 1559595546),
|
21
|
1
|
(1, 534011718),
|
22
|
1
|
};
|
23
|
1
|
var address = new Address("21744f4f08db23e044178dafb8273aeb5ebe6644");
|
24
|
1
|
foreach (var (seed, expected) in testCases)
|
25
|
1
|
{
|
26
|
1
|
var context = new ActionContext(
|
27
|
1
|
signer: address,
|
28
|
1
|
miner: address,
|
29
|
1
|
blockIndex: 1,
|
30
|
1
|
previousStates: new DumbAccountStateDelta(),
|
31
|
1
|
randomSeed: seed
|
32
|
1
|
);
|
33
|
1
|
IRandom random = context.Random;
|
34
|
1
|
Assert.Equal(expected, random.Next());
|
35
|
1
|
}
|
36
|
1
|
}
|
37
|
|
|
38
|
|
[Fact]
|
39
|
|
public void GuidShouldBeDeterministic()
|
40
|
1
|
{
|
41
|
1
|
var address = new Address("21744f4f08db23e044178dafb8273aeb5ebe6644");
|
42
|
1
|
var context1 = new ActionContext(
|
43
|
1
|
signer: address,
|
44
|
1
|
miner: address,
|
45
|
1
|
blockIndex: 1,
|
46
|
1
|
previousStates: new DumbAccountStateDelta(),
|
47
|
1
|
randomSeed: 0
|
48
|
1
|
);
|
49
|
|
|
50
|
1
|
var context2 = new ActionContext(
|
51
|
1
|
signer: address,
|
52
|
1
|
miner: address,
|
53
|
1
|
blockIndex: 1,
|
54
|
1
|
previousStates: new DumbAccountStateDelta(),
|
55
|
1
|
randomSeed: 0
|
56
|
1
|
);
|
57
|
|
|
58
|
1
|
var context3 = new ActionContext(
|
59
|
1
|
signer: address,
|
60
|
1
|
miner: address,
|
61
|
1
|
blockIndex: 1,
|
62
|
1
|
previousStates: new DumbAccountStateDelta(),
|
63
|
1
|
randomSeed: 1
|
64
|
1
|
);
|
65
|
|
|
66
|
1
|
(Guid Expected, Guid Diff)[] testCases =
|
67
|
1
|
{
|
68
|
1
|
(
|
69
|
1
|
new Guid("6f460c1a-755d-48e4-ad67-65d5f519dbc8"),
|
70
|
1
|
new Guid("8286d046-9740-43e4-95cf-ff46699c73c4")
|
71
|
1
|
),
|
72
|
1
|
(
|
73
|
1
|
new Guid("3b347c2b-f837-4085-ac5e-64005393b30d"),
|
74
|
1
|
new Guid("3410cda1-5b13-434e-af84-a54adf7a0ea0")
|
75
|
1
|
),
|
76
|
1
|
};
|
77
|
|
|
78
|
1
|
foreach (var (expected, diff) in testCases)
|
79
|
1
|
{
|
80
|
1
|
Assert.Equal(expected, context1.Random.GenerateRandomGuid());
|
81
|
1
|
Assert.Equal(expected, context2.Random.GenerateRandomGuid());
|
82
|
1
|
Assert.Equal(diff, context3.Random.GenerateRandomGuid());
|
83
|
1
|
}
|
84
|
1
|
}
|
85
|
|
|
86
|
|
[Fact]
|
87
|
|
public void GuidVersionAndVariant()
|
88
|
1
|
{
|
89
|
1
|
var address = new Address("21744f4f08db23e044178dafb8273aeb5ebe6644");
|
90
|
|
|
91
|
1
|
for (var i = 0; i < 100; i++)
|
92
|
1
|
{
|
93
|
1
|
var context = new ActionContext(
|
94
|
1
|
signer: address,
|
95
|
1
|
miner: address,
|
96
|
1
|
blockIndex: 1,
|
97
|
1
|
previousStates: new DumbAccountStateDelta(),
|
98
|
1
|
randomSeed: i
|
99
|
1
|
);
|
100
|
1
|
var guid = context.Random.GenerateRandomGuid().ToString();
|
101
|
|
|
102
|
1
|
Assert.Equal('4', guid[14]);
|
103
|
1
|
Assert.True(guid[19] >= '8' && guid[19] <= 'b');
|
104
|
1
|
}
|
105
|
1
|
}
|
106
|
|
|
107
|
|
[Fact]
|
108
|
|
public void GetUnconsumedContext()
|
109
|
1
|
{
|
110
|
1
|
var random = new System.Random();
|
111
|
1
|
var original = new ActionContext(
|
112
|
1
|
signer: random.NextAddress(),
|
113
|
1
|
miner: random.NextAddress(),
|
114
|
1
|
blockIndex: 1,
|
115
|
1
|
previousStates: new DumbAccountStateDelta(),
|
116
|
1
|
randomSeed: random.Next()
|
117
|
1
|
);
|
118
|
|
|
119
|
|
// Consume original's random state...
|
120
|
1
|
int[] values =
|
121
|
1
|
{
|
122
|
1
|
original.Random.Next(),
|
123
|
1
|
original.Random.Next(),
|
124
|
1
|
original.Random.Next(),
|
125
|
1
|
};
|
126
|
|
|
127
|
1
|
IActionContext clone = original.GetUnconsumedContext();
|
128
|
1
|
Assert.Equal(
|
129
|
1
|
values,
|
130
|
1
|
new[] { clone.Random.Next(), clone.Random.Next(), clone.Random.Next() }
|
131
|
1
|
);
|
132
|
1
|
}
|
133
|
|
|
134
|
|
[Theory]
|
135
|
|
[InlineData(true)]
|
136
|
|
[InlineData(false)]
|
137
|
|
public void LazyPreviousStateRootHash(bool callPreviousStateRootHash)
|
138
|
1
|
{
|
139
|
1
|
var keyValueStore = new MemoryKeyValueStore();
|
140
|
1
|
ITrie previousBlockStatesTrie = new MerkleTrie(keyValueStore);
|
141
|
1
|
previousBlockStatesTrie = previousBlockStatesTrie.Set(new byte[0], default(Null));
|
142
|
1
|
var random = new System.Random();
|
143
|
1
|
var actionContext = new ActionContext(
|
144
|
1
|
signer: random.NextAddress(),
|
145
|
1
|
miner: random.NextAddress(),
|
146
|
1
|
blockIndex: 1,
|
147
|
1
|
previousStates: new DumbAccountStateDelta(),
|
148
|
1
|
randomSeed: random.Next(),
|
149
|
1
|
previousBlockStatesTrie: previousBlockStatesTrie
|
150
|
1
|
);
|
151
|
|
|
152
|
1
|
if (callPreviousStateRootHash)
|
153
|
1
|
{
|
154
|
1
|
_ = actionContext.PreviousStateRootHash;
|
155
|
1
|
}
|
156
|
|
|
157
|
1
|
Assert.Equal(callPreviousStateRootHash ? 1 : 0, keyValueStore.ListKeys().Count());
|
158
|
1
|
}
|
159
|
|
|
160
|
|
private class DumbAccountStateDelta : IAccountStateDelta
|
161
|
|
{
|
162
|
|
public IImmutableSet<Address> UpdatedAddresses =>
|
163
|
0
|
ImmutableHashSet<Address>.Empty;
|
164
|
|
|
165
|
|
public IImmutableSet<Address> StateUpdatedAddresses =>
|
166
|
1
|
ImmutableHashSet<Address>.Empty;
|
167
|
|
|
168
|
|
public IImmutableDictionary<Address, IImmutableSet<Currency>>
|
169
|
|
UpdatedFungibleAssets =>
|
170
|
1
|
ImmutableDictionary<Address, IImmutableSet<Currency>>.Empty;
|
171
|
|
|
172
|
0
|
public IValue GetState(Address address) => null;
|
173
|
|
|
174
|
0
|
public IAccountStateDelta SetState(Address address, IValue state) => this;
|
175
|
|
|
176
|
|
public FungibleAssetValue GetBalance(Address address, Currency currency) =>
|
177
|
0
|
new FungibleAssetValue(currency);
|
178
|
|
|
179
|
|
public IAccountStateDelta MintAsset(Address recipient, FungibleAssetValue value) =>
|
180
|
0
|
this;
|
181
|
|
|
182
|
|
public IAccountStateDelta TransferAsset(
|
183
|
|
Address sender,
|
184
|
|
Address recipient,
|
185
|
|
FungibleAssetValue value,
|
186
|
|
bool allowNegativeBalance = false
|
187
|
0
|
) => this;
|
188
|
|
|
189
|
0
|
public IAccountStateDelta BurnAsset(Address owner, FungibleAssetValue value) => this;
|
190
|
|
}
|
191
|
|
}
|
192
|
|
}
|