Skip to content

Commit 5afab57

Browse files
committed
Merge branch 'chainstate-update'
2 parents d73ad6d + 4be9b9d commit 5afab57

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1603
-870
lines changed

Framework/DiscordRewards/CheckConfig.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ public class CheckConfig
1313
public enum CheckType
1414
{
1515
Uninitialized,
16-
FilledSlot,
17-
FinishedSlot,
18-
PostedContract,
19-
StartedContract,
16+
HostFilledSlot,
17+
HostFinishedSlot,
18+
ClientPostedContract,
19+
ClientStartedContract,
2020
}
2121
}

Framework/DiscordRewards/GiveRewardsCommand.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ public class GiveRewardsCommand
55
public RewardUsersCommand[] Rewards { get; set; } = Array.Empty<RewardUsersCommand>();
66
public MarketAverage[] Averages { get; set; } = Array.Empty<MarketAverage>();
77
public string[] EventsOverview { get; set; } = Array.Empty<string>();
8+
9+
public bool HasAny()
10+
{
11+
return Rewards.Any() || Averages.Any() || EventsOverview.Any();
12+
}
813
}
914

1015
public class RewardUsersCommand

Framework/DiscordRewards/RewardRepo.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,39 +11,39 @@ public class RewardRepo
1111
// Filled any slot
1212
new RewardConfig(1187039439558541498, $"{Tag} successfully filled their first slot!", new CheckConfig
1313
{
14-
Type = CheckType.FilledSlot
14+
Type = CheckType.HostFilledSlot
1515
}),
1616

1717
// Finished any slot
1818
new RewardConfig(1202286165630390339, $"{Tag} successfully finished their first slot!", new CheckConfig
1919
{
20-
Type = CheckType.FinishedSlot
20+
Type = CheckType.HostFinishedSlot
2121
}),
2222

2323
// Finished a sizable slot
2424
new RewardConfig(1202286218738405418, $"{Tag} finished their first 1GB-24h slot! (10mb/5mins for test)", new CheckConfig
2525
{
26-
Type = CheckType.FinishedSlot,
26+
Type = CheckType.HostFinishedSlot,
2727
MinSlotSize = 10.MB(),
2828
MinDuration = TimeSpan.FromMinutes(5.0),
2929
}),
3030

3131
// Posted any contract
3232
new RewardConfig(1202286258370383913, $"{Tag} posted their first contract!", new CheckConfig
3333
{
34-
Type = CheckType.PostedContract
34+
Type = CheckType.ClientPostedContract
3535
}),
3636

3737
// Started any contract
3838
new RewardConfig(1202286330873126992, $"A contract created by {Tag} reached Started state for the first time!", new CheckConfig
3939
{
40-
Type = CheckType.StartedContract
40+
Type = CheckType.ClientStartedContract
4141
}),
4242

4343
// Started a sizable contract
4444
new RewardConfig(1202286381670608909, $"A large contract created by {Tag} reached Started state for the first time! (10mb/5mins for test)", new CheckConfig
4545
{
46-
Type = CheckType.StartedContract,
46+
Type = CheckType.ClientStartedContract,
4747
MinNumberOfHosts = 4,
4848
MinSlotSize = 10.MB(),
4949
MinDuration = TimeSpan.FromMinutes(5.0),

Framework/NethereumWorkflow/NethereumInteraction.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ public BlockInterval ConvertTimeRangeToBlockRange(TimeRange timeRange)
117117
}
118118

119119
return new BlockInterval(
120+
timeRange: timeRange,
120121
from: fromBlock.Value,
121122
to: toBlock.Value
122123
);

Framework/Utils/BlockInterval.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
{
33
public class BlockInterval
44
{
5-
public BlockInterval(ulong from, ulong to)
5+
public BlockInterval(TimeRange timeRange, ulong from, ulong to)
66
{
77
if (from < to)
88
{
@@ -14,10 +14,13 @@ public BlockInterval(ulong from, ulong to)
1414
From = to;
1515
To = from;
1616
}
17+
TimeRange = timeRange;
1718
}
1819

1920
public ulong From { get; }
2021
public ulong To { get; }
22+
public TimeRange TimeRange { get; }
23+
public ulong NumberOfBlocks => To - From;
2124

2225
public override string ToString()
2326
{
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
using CodexContractsPlugin.Marketplace;
2+
using Utils;
3+
4+
namespace CodexContractsPlugin.ChainMonitor
5+
{
6+
public class ChainEvents
7+
{
8+
private ChainEvents(
9+
BlockInterval blockInterval,
10+
Request[] requests,
11+
RequestFulfilledEventDTO[] fulfilled,
12+
RequestCancelledEventDTO[] cancelled,
13+
SlotFilledEventDTO[] slotFilled,
14+
SlotFreedEventDTO[] slotFreed
15+
)
16+
{
17+
BlockInterval = blockInterval;
18+
Requests = requests;
19+
Fulfilled = fulfilled;
20+
Cancelled = cancelled;
21+
SlotFilled = slotFilled;
22+
SlotFreed = slotFreed;
23+
}
24+
25+
public BlockInterval BlockInterval { get; }
26+
public Request[] Requests { get; }
27+
public RequestFulfilledEventDTO[] Fulfilled { get; }
28+
public RequestCancelledEventDTO[] Cancelled { get; }
29+
public SlotFilledEventDTO[] SlotFilled { get; }
30+
public SlotFreedEventDTO[] SlotFreed { get; }
31+
32+
public IHasBlock[] All
33+
{
34+
get
35+
{
36+
var all = new List<IHasBlock>();
37+
all.AddRange(Requests);
38+
all.AddRange(Fulfilled);
39+
all.AddRange(Cancelled);
40+
all.AddRange(SlotFilled);
41+
all.AddRange(SlotFreed);
42+
return all.ToArray();
43+
}
44+
}
45+
46+
public static ChainEvents FromBlockInterval(ICodexContracts contracts, BlockInterval blockInterval)
47+
{
48+
return FromContractEvents(contracts.GetEvents(blockInterval));
49+
}
50+
51+
public static ChainEvents FromTimeRange(ICodexContracts contracts, TimeRange timeRange)
52+
{
53+
return FromContractEvents(contracts.GetEvents(timeRange));
54+
}
55+
56+
public static ChainEvents FromContractEvents(ICodexContractsEvents events)
57+
{
58+
return new ChainEvents(
59+
events.BlockInterval,
60+
events.GetStorageRequests(),
61+
events.GetRequestFulfilledEvents(),
62+
events.GetRequestCancelledEvents(),
63+
events.GetSlotFilledEvents(),
64+
events.GetSlotFreedEvents()
65+
);
66+
}
67+
}
68+
}
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
using CodexContractsPlugin.Marketplace;
2+
using Logging;
3+
using System.Numerics;
4+
using Utils;
5+
6+
namespace CodexContractsPlugin.ChainMonitor
7+
{
8+
public interface IChainStateChangeHandler
9+
{
10+
void OnNewRequest(IChainStateRequest request);
11+
void OnRequestFinished(IChainStateRequest request);
12+
void OnRequestFulfilled(IChainStateRequest request);
13+
void OnRequestCancelled(IChainStateRequest request);
14+
void OnSlotFilled(IChainStateRequest request, BigInteger slotIndex);
15+
void OnSlotFreed(IChainStateRequest request, BigInteger slotIndex);
16+
}
17+
18+
public class ChainState
19+
{
20+
private readonly List<ChainStateRequest> requests = new List<ChainStateRequest>();
21+
private readonly ILog log;
22+
private readonly ICodexContracts contracts;
23+
private readonly IChainStateChangeHandler handler;
24+
25+
public ChainState(ILog log, ICodexContracts contracts, IChainStateChangeHandler changeHandler, DateTime startUtc)
26+
{
27+
this.log = new LogPrefixer(log, "(ChainState) ");
28+
this.contracts = contracts;
29+
handler = changeHandler;
30+
StartUtc = startUtc;
31+
TotalSpan = new TimeRange(startUtc, startUtc);
32+
}
33+
34+
public TimeRange TotalSpan { get; private set; }
35+
public IChainStateRequest[] Requests => requests.ToArray();
36+
37+
public DateTime StartUtc { get; }
38+
39+
public void Update()
40+
{
41+
Update(DateTime.UtcNow);
42+
}
43+
44+
public void Update(DateTime toUtc)
45+
{
46+
var span = new TimeRange(TotalSpan.To, toUtc);
47+
var events = ChainEvents.FromTimeRange(contracts, span);
48+
Apply(events);
49+
50+
TotalSpan = new TimeRange(TotalSpan.From, span.To);
51+
}
52+
53+
private void Apply(ChainEvents events)
54+
{
55+
if (events.BlockInterval.TimeRange.From < TotalSpan.From)
56+
throw new Exception("Attempt to update ChainState with set of events from before its current record.");
57+
58+
log.Log($"ChainState updating: {events.BlockInterval}");
59+
60+
// Run through each block and apply the events to the state in order.
61+
var span = events.BlockInterval.TimeRange.Duration;
62+
var numBlocks = events.BlockInterval.NumberOfBlocks;
63+
var spanPerBlock = span / numBlocks;
64+
65+
var eventUtc = events.BlockInterval.TimeRange.From;
66+
for (var b = events.BlockInterval.From; b <= events.BlockInterval.To; b++)
67+
{
68+
var blockEvents = events.All.Where(e => e.Block.BlockNumber == b).ToArray();
69+
ApplyEvents(b, blockEvents, eventUtc);
70+
71+
eventUtc += spanPerBlock;
72+
}
73+
}
74+
75+
private void ApplyEvents(ulong blockNumber, IHasBlock[] blockEvents, DateTime eventsUtc)
76+
{
77+
foreach (var e in blockEvents)
78+
{
79+
dynamic d = e;
80+
ApplyEvent(d);
81+
}
82+
83+
ApplyTimeImplicitEvents(blockNumber, eventsUtc);
84+
}
85+
86+
private void ApplyEvent(Request request)
87+
{
88+
if (requests.Any(r => Equal(r.Request.RequestId, request.RequestId)))
89+
throw new Exception("Received NewRequest event for id that already exists.");
90+
91+
var newRequest = new ChainStateRequest(log, request, RequestState.New);
92+
requests.Add(newRequest);
93+
94+
handler.OnNewRequest(newRequest);
95+
}
96+
97+
private void ApplyEvent(RequestFulfilledEventDTO request)
98+
{
99+
var r = FindRequest(request.RequestId);
100+
if (r == null) return;
101+
r.UpdateState(request.Block.BlockNumber, RequestState.Started);
102+
handler.OnRequestFulfilled(r);
103+
}
104+
105+
private void ApplyEvent(RequestCancelledEventDTO request)
106+
{
107+
var r = FindRequest(request.RequestId);
108+
if (r == null) return;
109+
r.UpdateState(request.Block.BlockNumber, RequestState.Cancelled);
110+
handler.OnRequestCancelled(r);
111+
}
112+
113+
private void ApplyEvent(SlotFilledEventDTO request)
114+
{
115+
var r = FindRequest(request.RequestId);
116+
if (r == null) return;
117+
r.Hosts.Add(request.Host, (int)request.SlotIndex);
118+
r.Log($"[{request.Block.BlockNumber}] SlotFilled (host:'{request.Host}', slotIndex:{request.SlotIndex})");
119+
handler.OnSlotFilled(r, request.SlotIndex);
120+
}
121+
122+
private void ApplyEvent(SlotFreedEventDTO request)
123+
{
124+
var r = FindRequest(request.RequestId);
125+
if (r == null) return;
126+
r.Hosts.RemoveHost((int)request.SlotIndex);
127+
r.Log($"[{request.Block.BlockNumber}] SlotFreed (slotIndex:{request.SlotIndex})");
128+
handler.OnSlotFreed(r, request.SlotIndex);
129+
}
130+
131+
private void ApplyTimeImplicitEvents(ulong blockNumber, DateTime eventsUtc)
132+
{
133+
foreach (var r in requests)
134+
{
135+
if (r.State == RequestState.Started
136+
&& r.FinishedUtc < eventsUtc)
137+
{
138+
r.UpdateState(blockNumber, RequestState.Finished);
139+
handler.OnRequestFinished(r);
140+
}
141+
}
142+
}
143+
144+
private ChainStateRequest? FindRequest(byte[] requestId)
145+
{
146+
var r = requests.SingleOrDefault(r => Equal(r.Request.RequestId, requestId));
147+
if (r == null) log.Log("Unable to find request by ID!");
148+
return r;
149+
}
150+
151+
private bool Equal(byte[] a, byte[] b)
152+
{
153+
return a.SequenceEqual(b);
154+
}
155+
}
156+
}

0 commit comments

Comments
 (0)