Compare commits

...
Author SHA1 Message Date
benbierens 7eed6160eb working as intended 2024-06-28 09:16:12 +02:00
benbierens c57dc4daa1 concurrent purchases 2024-06-28 08:47:09 +02:00
Ben 4c75cebcd6 Implements autoclient with image generator 2024-06-27 15:38:13 +02:00
Ben a820788c7d Merge branch 'master' into feature/auto-client
# Conflicts:
#	cs-codex-dist-testing.sln
2024-06-27 13:42:54 +02:00
Ben 52a02abd3f Fixes incorrect block numbers in eventFormatter 2024-06-27 11:43:25 +02:00
Ben a92455b2a5 bump codex image to v0.1.2 + prover 2024-06-27 11:16:50 +02:00
Ben 933d5e7d4d Merge branch 'better-chain-events' 2024-06-27 11:16:34 +02:00
benbierens 362040bd3c Sets up docker image and CI 2024-04-01 21:29:02 +02:00
benbierens 40393c3a5b Using raw version of purchase-status call. API doesn't line up 2024-04-01 21:09:24 +02:00
benbierens 7f972bac85 Mvoes autoclient 2024-04-01 20:47:56 +02:00
benbierens d532d9505a Sets up autoclient. 2024-04-01 20:40:03 +02:00
18 changed files with 505 additions and 98 deletions
+26
View File
@@ -0,0 +1,26 @@
name: Docker - AutoClient
on:
push:
branches:
- master
tags:
- 'v*.*.*'
paths:
- 'Tools/AutoClient/**'
- '!Tools/AutoClient/docker/docker-compose.yaml'
- 'Framework/**'
- 'ProjectPlugins/**'
- .github/workflows/docker-autoclient.yml
- .github/workflows/docker-reusable.yml
workflow_dispatch:
jobs:
build-and-push:
name: Build and Push
uses: ./.github/workflows/docker-reusable.yml
with:
docker_file: Tools/AutoClient/docker/Dockerfile
docker_repo: codexstorage/codex-autoclient
secrets: inherit
+2 -1
View File
@@ -1,4 +1,5 @@
.vs
obj
bin
.vscode
.vscode
Tools/AutoClient/datapath
+16 -5
View File
@@ -57,16 +57,27 @@ namespace FileUtils
public void ScopedFiles(Action action)
{
PushFileSet();
action();
PopFileSet();
try
{
action();
}
finally
{
PopFileSet();
}
}
public T ScopedFiles<T>(Func<T> action)
{
PushFileSet();
var result = action();
PopFileSet();
return result;
try
{
return action();
}
finally
{
PopFileSet();
}
}
private void PushFileSet()
@@ -1,6 +1,7 @@
using CodexContractsPlugin.Marketplace;
using GethPlugin;
using Logging;
using NethereumWorkflow.BlockUtils;
using System.Numerics;
using Utils;
@@ -8,12 +9,24 @@ namespace CodexContractsPlugin.ChainMonitor
{
public interface IChainStateChangeHandler
{
void OnNewRequest(IChainStateRequest request);
void OnRequestFinished(IChainStateRequest request);
void OnRequestFulfilled(IChainStateRequest request);
void OnRequestCancelled(IChainStateRequest request);
void OnSlotFilled(IChainStateRequest request, EthAddress host, BigInteger slotIndex);
void OnSlotFreed(IChainStateRequest request, BigInteger slotIndex);
void OnNewRequest(RequestEvent requestEvent);
void OnRequestFinished(RequestEvent requestEvent);
void OnRequestFulfilled(RequestEvent requestEvent);
void OnRequestCancelled(RequestEvent requestEvent);
void OnSlotFilled(RequestEvent requestEvent, EthAddress host, BigInteger slotIndex);
void OnSlotFreed(RequestEvent requestEvent, BigInteger slotIndex);
}
public class RequestEvent
{
public RequestEvent(BlockTimeEntry block, IChainStateRequest request)
{
Block = block;
Request = request;
}
public BlockTimeEntry Block { get; }
public IChainStateRequest Request { get; }
}
public class ChainState
@@ -92,41 +105,41 @@ namespace CodexContractsPlugin.ChainMonitor
var newRequest = new ChainStateRequest(log, request, RequestState.New);
requests.Add(newRequest);
handler.OnNewRequest(newRequest);
handler.OnNewRequest(new RequestEvent(request.Block, newRequest));
}
private void ApplyEvent(RequestFulfilledEventDTO request)
private void ApplyEvent(RequestFulfilledEventDTO @event)
{
var r = FindRequest(request.RequestId);
var r = FindRequest(@event.RequestId);
if (r == null) return;
r.UpdateState(request.Block.BlockNumber, RequestState.Started);
handler.OnRequestFulfilled(r);
r.UpdateState(@event.Block.BlockNumber, RequestState.Started);
handler.OnRequestFulfilled(new RequestEvent(@event.Block, r));
}
private void ApplyEvent(RequestCancelledEventDTO request)
private void ApplyEvent(RequestCancelledEventDTO @event)
{
var r = FindRequest(request.RequestId);
var r = FindRequest(@event.RequestId);
if (r == null) return;
r.UpdateState(request.Block.BlockNumber, RequestState.Cancelled);
handler.OnRequestCancelled(r);
r.UpdateState(@event.Block.BlockNumber, RequestState.Cancelled);
handler.OnRequestCancelled(new RequestEvent(@event.Block, r));
}
private void ApplyEvent(SlotFilledEventDTO request)
private void ApplyEvent(SlotFilledEventDTO @event)
{
var r = FindRequest(request.RequestId);
var r = FindRequest(@event.RequestId);
if (r == null) return;
r.Hosts.Add(request.Host, (int)request.SlotIndex);
r.Log($"[{request.Block.BlockNumber}] SlotFilled (host:'{request.Host}', slotIndex:{request.SlotIndex})");
handler.OnSlotFilled(r, request.Host, request.SlotIndex);
r.Hosts.Add(@event.Host, (int)@event.SlotIndex);
r.Log($"[{@event.Block.BlockNumber}] SlotFilled (host:'{@event.Host}', slotIndex:{@event.SlotIndex})");
handler.OnSlotFilled(new RequestEvent(@event.Block, r), @event.Host, @event.SlotIndex);
}
private void ApplyEvent(SlotFreedEventDTO request)
private void ApplyEvent(SlotFreedEventDTO @event)
{
var r = FindRequest(request.RequestId);
var r = FindRequest(@event.RequestId);
if (r == null) return;
r.Hosts.RemoveHost((int)request.SlotIndex);
r.Log($"[{request.Block.BlockNumber}] SlotFreed (slotIndex:{request.SlotIndex})");
handler.OnSlotFreed(r, request.SlotIndex);
r.Hosts.RemoveHost((int)@event.SlotIndex);
r.Log($"[{@event.Block.BlockNumber}] SlotFreed (slotIndex:{@event.SlotIndex})");
handler.OnSlotFreed(new RequestEvent(@event.Block, r), @event.SlotIndex);
}
private void ApplyTimeImplicitEvents(ulong blockNumber, DateTime eventsUtc)
@@ -137,7 +150,7 @@ namespace CodexContractsPlugin.ChainMonitor
&& r.FinishedUtc < eventsUtc)
{
r.UpdateState(blockNumber, RequestState.Finished);
handler.OnRequestFinished(r);
handler.OnRequestFinished(new RequestEvent(new BlockTimeEntry(blockNumber, eventsUtc), r));
}
}
}
@@ -5,27 +5,27 @@ namespace CodexContractsPlugin.ChainMonitor
{
public class DoNothingChainEventHandler : IChainStateChangeHandler
{
public void OnNewRequest(IChainStateRequest request)
public void OnNewRequest(RequestEvent requestEvent)
{
}
public void OnRequestCancelled(IChainStateRequest request)
public void OnRequestCancelled(RequestEvent requestEvent)
{
}
public void OnRequestFinished(IChainStateRequest request)
public void OnRequestFinished(RequestEvent requestEvent)
{
}
public void OnRequestFulfilled(IChainStateRequest request)
public void OnRequestFulfilled(RequestEvent requestEvent)
{
}
public void OnSlotFilled(IChainStateRequest request, EthAddress host, BigInteger slotIndex)
public void OnSlotFilled(RequestEvent requestEvent, EthAddress host, BigInteger slotIndex)
{
}
public void OnSlotFreed(IChainStateRequest request, BigInteger slotIndex)
public void OnSlotFreed(RequestEvent requestEvent, BigInteger slotIndex)
{
}
}
@@ -7,7 +7,7 @@ namespace CodexPlugin
{
public class CodexContainerRecipe : ContainerRecipeFactory
{
private const string DefaultDockerImage = "codexstorage/nim-codex:sha-305b80a-dist-tests";
private const string DefaultDockerImage = "codexstorage/nim-codex:sha-471ebb2-dist-tests";
public const string ApiPortTag = "codex_api_port";
public const string ListenPortTag = "codex_listen_port";
+16
View File
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Framework\ArgsUniform\ArgsUniform.csproj" />
<ProjectReference Include="..\..\Framework\Logging\Logging.csproj" />
<ProjectReference Include="..\..\ProjectPlugins\CodexPlugin\CodexPlugin.csproj" />
</ItemGroup>
</Project>
+45
View File
@@ -0,0 +1,45 @@
using ArgsUniform;
namespace AutoClient
{
public class Configuration
{
[Uniform("codex-host", "ch", "CODEXHOST", false, "Codex Host address. (default 'http://localhost')")]
public string CodexHost { get; set; } = "http://localhost";
[Uniform("codex-port", "cp", "CODEXPORT", false, "port number of Codex API. (8080 by default)")]
public int CodexPort { get; set; } = 8080;
[Uniform("datapath", "dp", "DATAPATH", false, "Root path where all data files will be saved.")]
public string DataPath { get; set; } = "datapath";
[Uniform("purchases", "np", "PURCHASES", false, "Number of concurrent purchases.")]
public int NumConcurrentPurchases { get; set; } = 10;
[Uniform("contract-duration", "cd", "CONTRACTDURATION", false, "contract duration in minutes. (default 30)")]
public int ContractDurationMinutes { get; set; } = 30;
[Uniform("contract-expiry", "ce", "CONTRACTEXPIRY", false, "contract expiry in minutes. (default 15)")]
public int ContractExpiryMinutes { get; set; } = 15;
[Uniform("num-hosts", "nh", "NUMHOSTS", false, "Number of hosts for contract. (default 5)")]
public int NumHosts { get; set; } = 5;
[Uniform("num-hosts-tolerance", "nt", "NUMTOL", false, "Number of host tolerance for contract. (default 2)")]
public int HostTolerance { get; set; } = 2;
[Uniform("price","p", "PRICE", false, "Price of contract. (default 10)")]
public int Price { get; set; } = 10;
[Uniform("collateral", "c", "COLLATERAL", false, "Required collateral. (default 1)")]
public int RequiredCollateral { get; set; } = 1;
public string LogPath
{
get
{
return Path.Combine(DataPath, "logs");
}
}
}
}
+17
View File
@@ -0,0 +1,17 @@
namespace AutoClient
{
public class ImageGenerator
{
public async Task<string> GenerateImage()
{
var httpClient = new HttpClient();
var thing = await httpClient.GetStreamAsync("https://picsum.photos/3840/2160");
var filename = $"{Guid.NewGuid().ToString().ToLowerInvariant()}.jpg";
using var file = File.OpenWrite(filename);
await thing.CopyToAsync(file);
return filename;
}
}
}
+80
View File
@@ -0,0 +1,80 @@
using ArgsUniform;
using AutoClient;
using CodexOpenApi;
using Core;
using Logging;
public static class Program
{
public static async Task Main(string[] args)
{
var cts = new CancellationTokenSource();
var cancellationToken = cts.Token;
Console.CancelKeyPress += (sender, args) => cts.Cancel();
var uniformArgs = new ArgsUniform<Configuration>(PrintHelp, args);
var config = uniformArgs.Parse(true);
if (config.NumConcurrentPurchases < 1)
{
throw new Exception("Number of concurrent purchases must be > 0");
}
var log = new LogSplitter(
new FileLog(Path.Combine(config.LogPath, "autoclient")),
new ConsoleLog()
);
var address = new Utils.Address(
host: config.CodexHost,
port: config.CodexPort
);
log.Log($"Start. Address: {address}");
var imgGenerator = new ImageGenerator();
var client = new HttpClient();
var codex = new CodexApi(client);
codex.BaseUrl = $"{address.Host}:{address.Port}/api/codex/v1";
await CheckCodex(codex, log);
var purchasers = new List<Purchaser>();
for (var i = 0; i < config.NumConcurrentPurchases; i++)
{
purchasers.Add(
new Purchaser(new LogPrefixer(log, $"({i}) "), client, address, codex, cancellationToken, config, imgGenerator)
);
}
var delayPerPurchaser = TimeSpan.FromMinutes(config.ContractDurationMinutes) / config.NumConcurrentPurchases;
foreach (var purchaser in purchasers)
{
purchaser.Start();
await Task.Delay(delayPerPurchaser);
}
log.Log("Done.");
}
private static async Task CheckCodex(CodexApi codex, ILog log)
{
log.Log("Checking Codex...");
try
{
var info = await codex.GetDebugInfoAsync();
if (string.IsNullOrEmpty(info.Id)) throw new Exception("Failed to fetch Codex node id");
}
catch (Exception ex)
{
log.Log($"Codex not OK: {ex}");
throw;
}
}
private static void PrintHelp()
{
Console.WriteLine("Generates fake data and creates Codex storage contracts for it.");
}
}
+166
View File
@@ -0,0 +1,166 @@
using CodexOpenApi;
using CodexPlugin;
using Logging;
using Newtonsoft.Json;
using Utils;
namespace AutoClient
{
public class Purchaser
{
private readonly ILog log;
private readonly HttpClient client;
private readonly Address address;
private readonly CodexApi codex;
private readonly CancellationToken ct;
private readonly Configuration config;
private readonly ImageGenerator generator;
public Purchaser(ILog log, HttpClient client, Address address, CodexApi codex, CancellationToken ct, Configuration config, ImageGenerator generator)
{
this.log = log;
this.client = client;
this.address = address;
this.codex = codex;
this.ct = ct;
this.config = config;
this.generator = generator;
}
public void Start()
{
Task.Run(Worker);
}
private async Task Worker()
{
while (!ct.IsCancellationRequested)
{
var pid = await StartNewPurchase();
await WaitTillFinished(pid);
}
}
private async Task<string> StartNewPurchase()
{
var file = await CreateFile();
var cid = await UploadFile(file);
return await RequestStorage(cid);
}
private async Task<string> CreateFile()
{
return await generator.GenerateImage();
}
private async Task<ContentId> UploadFile(string filename)
{
// Copied from CodexNode :/
using var fileStream = File.OpenRead(filename);
log.Log($"Uploading file {filename}...");
var response = await codex.UploadAsync(fileStream, ct);
if (string.IsNullOrEmpty(response)) FrameworkAssert.Fail("Received empty response.");
if (response.StartsWith("Unable to store block")) FrameworkAssert.Fail("Node failed to store block.");
log.Log($"Uploaded file. Received contentId: '{response}'.");
return new ContentId(response);
}
private async Task<string> RequestStorage(ContentId cid)
{
log.Log("Requesting storage for " + cid.Id);
var result = await codex.CreateStorageRequestAsync(cid.Id, new StorageRequestCreation()
{
Collateral = config.RequiredCollateral.ToString(),
Duration = (config.ContractDurationMinutes * 60).ToString(),
Expiry = (config.ContractExpiryMinutes * 60).ToString(),
Nodes = config.NumHosts,
Reward = config.Price.ToString(),
ProofProbability = "15",
Tolerance = config.HostTolerance
}, ct);
log.Log("Purchase ID: " + result);
return result;
}
private async Task<string?> GetPurchaseState(string pid)
{
try
{
// openapi still don't match code.
var str = await client.GetStringAsync($"{address.Host}:{address.Port}/api/codex/v1/storage/purchases/{pid}");
if (string.IsNullOrEmpty(str)) return null;
var sp = JsonConvert.DeserializeObject<StoragePurchase>(str)!;
log.Log($"Purchase {pid} is {sp.State}");
if (!string.IsNullOrEmpty(sp.Error)) log.Log($"Purchase {pid} error is {sp.Error}");
return sp.State;
}
catch
{
return null;
}
}
private async Task WaitTillFinished(string pid)
{
log.Log("Waiting...");
try
{
var emptyResponseTolerance = 10;
while (true)
{
var status = (await GetPurchaseState(pid))?.ToLowerInvariant();
if (string.IsNullOrEmpty(status))
{
emptyResponseTolerance--;
if (emptyResponseTolerance == 0)
{
log.Log("Received 10 empty responses. Stop tracking this purchase.");
await ExpiryTimeDelay();
return;
}
}
else
{
if (status.Contains("cancel") ||
status.Contains("error") ||
status.Contains("finished"))
{
return;
}
if (status.Contains("started"))
{
await FixedDurationDelay();
}
}
await FixedShortDelay();
}
}
catch (Exception ex)
{
log.Log($"Wait failed with exception: {ex}. Assume contract will expire: Wait expiry time.");
await ExpiryTimeDelay();
}
}
private async Task FixedDurationDelay()
{
await Task.Delay(config.ContractDurationMinutes * 60 * 1000, ct);
}
private async Task ExpiryTimeDelay()
{
await Task.Delay(config.ContractExpiryMinutes * 60 * 1000, ct);
}
private async Task FixedShortDelay()
{
await Task.Delay(15 * 1000, ct);
}
}
}
+24
View File
@@ -0,0 +1,24 @@
# Variables
ARG BUILDER=mcr.microsoft.com/dotnet/sdk:7.0
ARG IMAGE=${BUILDER}
ARG APP_HOME=/app
# Build
FROM ${IMAGE} AS builder
ARG APP_HOME
WORKDIR ${APP_HOME}
COPY ./Tools/AutoClient ./Tools/AutoClient
COPY ./Framework ./Framework
COPY ./ProjectPlugins ./ProjectPlugins
RUN dotnet restore Tools/AutoClient
RUN dotnet publish Tools/AutoClient -c Release -o out
# Create
FROM ${IMAGE}
ARG APP_HOME
ENV APP_HOME=${APP_HOME}
WORKDIR ${APP_HOME}
COPY --from=builder ${APP_HOME}/out .
CMD dotnet ${APP_HOME}/AutoClient.dll
+12 -12
View File
@@ -13,34 +13,34 @@ namespace TestNetRewarder
this.handlers = handlers;
}
public void OnNewRequest(IChainStateRequest request)
public void OnNewRequest(RequestEvent requestEvent)
{
foreach (var handler in handlers) handler.OnNewRequest(request);
foreach (var handler in handlers) handler.OnNewRequest(requestEvent);
}
public void OnRequestCancelled(IChainStateRequest request)
public void OnRequestCancelled(RequestEvent requestEvent)
{
foreach (var handler in handlers) handler.OnRequestCancelled(request);
foreach (var handler in handlers) handler.OnRequestCancelled(requestEvent);
}
public void OnRequestFinished(IChainStateRequest request)
public void OnRequestFinished(RequestEvent requestEvent)
{
foreach (var handler in handlers) handler.OnRequestFinished(request);
foreach (var handler in handlers) handler.OnRequestFinished(requestEvent);
}
public void OnRequestFulfilled(IChainStateRequest request)
public void OnRequestFulfilled(RequestEvent requestEvent)
{
foreach (var handler in handlers) handler.OnRequestFulfilled(request);
foreach (var handler in handlers) handler.OnRequestFulfilled(requestEvent);
}
public void OnSlotFilled(IChainStateRequest request, EthAddress host, BigInteger slotIndex)
public void OnSlotFilled(RequestEvent requestEvent, EthAddress host, BigInteger slotIndex)
{
foreach (var handler in handlers) handler.OnSlotFilled(request, host, slotIndex);
foreach (var handler in handlers) handler.OnSlotFilled(requestEvent, host, slotIndex);
}
public void OnSlotFreed(IChainStateRequest request, BigInteger slotIndex)
public void OnSlotFreed(RequestEvent requestEvent, BigInteger slotIndex)
{
foreach (var handler in handlers) handler.OnSlotFreed(request, slotIndex);
foreach (var handler in handlers) handler.OnSlotFreed(requestEvent, slotIndex);
}
}
}
+16 -15
View File
@@ -23,9 +23,10 @@ namespace TestNetRewarder
AddBlock("📢 **Error**", error);
}
public void OnNewRequest(IChainStateRequest request)
public void OnNewRequest(RequestEvent requestEvent)
{
AddRequestBlock(request, "New Request",
var request = requestEvent.Request;
AddRequestBlock(requestEvent, "New Request",
$"Client: {request.Client}",
$"Content: {request.Request.Content.Cid}",
$"Duration: {BigIntToDuration(request.Request.Ask.Duration)}",
@@ -38,40 +39,40 @@ namespace TestNetRewarder
);
}
public void OnRequestCancelled(IChainStateRequest request)
public void OnRequestCancelled(RequestEvent requestEvent)
{
AddRequestBlock(request, "Cancelled");
AddRequestBlock(requestEvent, "Cancelled");
}
public void OnRequestFinished(IChainStateRequest request)
public void OnRequestFinished(RequestEvent requestEvent)
{
AddRequestBlock(request, "Finished");
AddRequestBlock(requestEvent, "Finished");
}
public void OnRequestFulfilled(IChainStateRequest request)
public void OnRequestFulfilled(RequestEvent requestEvent)
{
AddRequestBlock(request, "Started");
AddRequestBlock(requestEvent, "Started");
}
public void OnSlotFilled(IChainStateRequest request, EthAddress host, BigInteger slotIndex)
public void OnSlotFilled(RequestEvent requestEvent, EthAddress host, BigInteger slotIndex)
{
AddRequestBlock(request, "Slot Filled",
AddRequestBlock(requestEvent, "Slot Filled",
$"Host: {host}",
$"Slot Index: {slotIndex}"
);
}
public void OnSlotFreed(IChainStateRequest request, BigInteger slotIndex)
public void OnSlotFreed(RequestEvent requestEvent, BigInteger slotIndex)
{
AddRequestBlock(request, "Slot Freed",
AddRequestBlock(requestEvent, "Slot Freed",
$"Slot Index: {slotIndex}"
);
}
private void AddRequestBlock(IChainStateRequest request, string eventName, params string[] content)
private void AddRequestBlock(RequestEvent requestEvent, string eventName, params string[] content)
{
var blockNumber = $"[{request.Request.Block.BlockNumber}]";
var title = $"{blockNumber} **{eventName}** `{request.Request.Id}`";
var blockNumber = $"[{requestEvent.Block.BlockNumber}]";
var title = $"{blockNumber} **{eventName}** `{requestEvent.Request.Request.Id}`";
AddBlock(title, content);
}
+9 -9
View File
@@ -7,7 +7,7 @@ namespace TestNetRewarder
{
public class MarketBuffer
{
private readonly List<IChainStateRequest> requests = new List<IChainStateRequest>();
private readonly List<RequestEvent> requestEvents = new List<RequestEvent>();
private readonly TimeSpan bufferSpan;
public MarketBuffer(TimeSpan bufferSpan)
@@ -15,24 +15,24 @@ namespace TestNetRewarder
this.bufferSpan = bufferSpan;
}
public void Add(IChainStateRequest request)
public void Add(RequestEvent requestEvent)
{
requests.Add(request);
requestEvents.Add(requestEvent);
}
public void Update()
{
var now = DateTime.UtcNow;
requests.RemoveAll(r => (now - r.FinishedUtc) > bufferSpan);
requestEvents.RemoveAll(r => (now - r.Request.FinishedUtc) > bufferSpan);
}
public MarketAverage? GetAverage()
{
if (requests.Count == 0) return null;
if (requestEvents.Count == 0) return null;
return new MarketAverage
{
NumberOfFinished = requests.Count,
NumberOfFinished = requestEvents.Count,
TimeRangeSeconds = (int)bufferSpan.TotalSeconds,
Price = Average(s => s.Request.Ask.Reward),
Duration = Average(s => s.Request.Ask.Duration),
@@ -54,10 +54,10 @@ namespace TestNetRewarder
private float Average(Func<IChainStateRequest, int> getValue)
{
var sum = 0.0f;
float count = requests.Count;
foreach (var r in requests)
float count = requestEvents.Count;
foreach (var r in requestEvents)
{
sum += getValue(r);
sum += getValue(r.Request);
}
if (count < 1.0f) return 0.0f;
+7 -7
View File
@@ -32,28 +32,28 @@ namespace TestNetRewarder
return buffers.Select(b => b.GetAverage()).Where(a => a != null).Cast<MarketAverage>().ToArray();
}
public void OnNewRequest(IChainStateRequest request)
public void OnNewRequest(RequestEvent requestEvent)
{
}
public void OnRequestFinished(IChainStateRequest request)
public void OnRequestFinished(RequestEvent requestEvent)
{
foreach (var b in buffers) b.Add(request);
foreach (var b in buffers) b.Add(requestEvent);
}
public void OnRequestFulfilled(IChainStateRequest request)
public void OnRequestFulfilled(RequestEvent requestEvent)
{
}
public void OnRequestCancelled(IChainStateRequest request)
public void OnRequestCancelled(RequestEvent requestEvent)
{
}
public void OnSlotFilled(IChainStateRequest request, EthAddress host, BigInteger slotIndex)
public void OnSlotFilled(RequestEvent requestEvent, EthAddress host, BigInteger slotIndex)
{
}
public void OnSlotFreed(IChainStateRequest request, BigInteger slotIndex)
public void OnSlotFreed(RequestEvent requestEvent, BigInteger slotIndex)
{
}
+16 -16
View File
@@ -22,40 +22,40 @@ namespace TestNetRewarder
this.giver = giver;
}
public void OnNewRequest(IChainStateRequest request)
public void OnNewRequest(RequestEvent requestEvent)
{
if (MeetsRequirements(CheckType.ClientPostedContract, request))
if (MeetsRequirements(CheckType.ClientPostedContract, requestEvent))
{
GiveReward(reward, request.Client);
GiveReward(reward, requestEvent.Request.Client);
}
}
public void OnRequestCancelled(IChainStateRequest request)
public void OnRequestCancelled(RequestEvent requestEvent)
{
}
public void OnRequestFinished(IChainStateRequest request)
public void OnRequestFinished(RequestEvent requestEvent)
{
if (MeetsRequirements(CheckType.HostFinishedSlot, request))
if (MeetsRequirements(CheckType.HostFinishedSlot, requestEvent))
{
foreach (var host in request.Hosts.GetHosts())
foreach (var host in requestEvent.Request.Hosts.GetHosts())
{
GiveReward(reward, host);
}
}
}
public void OnRequestFulfilled(IChainStateRequest request)
public void OnRequestFulfilled(RequestEvent requestEvent)
{
if (MeetsRequirements(CheckType.ClientStartedContract, request))
if (MeetsRequirements(CheckType.ClientStartedContract, requestEvent))
{
GiveReward(reward, request.Client);
GiveReward(reward, requestEvent.Request.Client);
}
}
public void OnSlotFilled(IChainStateRequest request, EthAddress host, BigInteger slotIndex)
public void OnSlotFilled(RequestEvent requestEvent, EthAddress host, BigInteger slotIndex)
{
if (MeetsRequirements(CheckType.HostFilledSlot, request))
if (MeetsRequirements(CheckType.HostFilledSlot, requestEvent))
{
if (host != null)
{
@@ -64,7 +64,7 @@ namespace TestNetRewarder
}
}
public void OnSlotFreed(IChainStateRequest request, BigInteger slotIndex)
public void OnSlotFreed(RequestEvent requestEvent, BigInteger slotIndex)
{
}
@@ -73,12 +73,12 @@ namespace TestNetRewarder
giver.Give(reward, receiver);
}
private bool MeetsRequirements(CheckType type, IChainStateRequest request)
private bool MeetsRequirements(CheckType type, RequestEvent requestEvent)
{
return
reward.CheckConfig.Type == type &&
MeetsDurationRequirement(request) &&
MeetsSizeRequirement(request);
MeetsDurationRequirement(requestEvent.Request) &&
MeetsSizeRequirement(requestEvent.Request);
}
private bool MeetsSizeRequirement(IChainStateRequest r)
+7
View File
@@ -66,6 +66,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
.editorconfig = .editorconfig
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoClient", "Tools\AutoClient\AutoClient.csproj", "{73599F9C-98BB-4C6A-9D7D-7C50FBF2993B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KeyMaker", "Tools\KeyMaker\KeyMaker.csproj", "{B57A4789-D8EF-42E0-8D20-581C4057FFD3}"
EndProject
Global
@@ -174,6 +176,10 @@ Global
{88C212E9-308A-46A4-BAAD-468E8EBD8EDF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{88C212E9-308A-46A4-BAAD-468E8EBD8EDF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{88C212E9-308A-46A4-BAAD-468E8EBD8EDF}.Release|Any CPU.Build.0 = Release|Any CPU
{73599F9C-98BB-4C6A-9D7D-7C50FBF2993B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{73599F9C-98BB-4C6A-9D7D-7C50FBF2993B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{73599F9C-98BB-4C6A-9D7D-7C50FBF2993B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{73599F9C-98BB-4C6A-9D7D-7C50FBF2993B}.Release|Any CPU.Build.0 = Release|Any CPU
{B57A4789-D8EF-42E0-8D20-581C4057FFD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B57A4789-D8EF-42E0-8D20-581C4057FFD3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B57A4789-D8EF-42E0-8D20-581C4057FFD3}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -208,6 +214,7 @@ Global
{F730DA73-1C92-4107-BCFB-D33759DAB0C3} = {81AE04BC-CBFA-4E6F-B039-8208E9AFAAE7}
{B07820C4-309F-4454-BCC1-1D4902C9C67B} = {81AE04BC-CBFA-4E6F-B039-8208E9AFAAE7}
{88C212E9-308A-46A4-BAAD-468E8EBD8EDF} = {8F1F1C2A-E313-4E0C-BE40-58FB0BA91124}
{73599F9C-98BB-4C6A-9D7D-7C50FBF2993B} = {7591C5B3-D86E-4AE4-8ED2-B272D17FE7E3}
{B57A4789-D8EF-42E0-8D20-581C4057FFD3} = {7591C5B3-D86E-4AE4-8ED2-B272D17FE7E3}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution