mirror of
https://github.com/logos-storage/logos-storage-nim-cs-dist-tests.git
synced 2026-01-02 13:33:07 +00:00
wip
This commit is contained in:
parent
62f7d65c2d
commit
4e093f12d7
@ -1,5 +1,6 @@
|
||||
using BlockchainUtils;
|
||||
using CodexContractsPlugin.Marketplace;
|
||||
using GethPlugin;
|
||||
using Logging;
|
||||
using Nethereum.Contracts;
|
||||
using Nethereum.Hex.HexConvertors.Extensions;
|
||||
@ -42,14 +43,14 @@ namespace CodexContractsPlugin.ChainMonitor
|
||||
private readonly IChainStateChangeHandler handler;
|
||||
private readonly bool doProofPeriodMonitoring;
|
||||
|
||||
public ChainState(ILog log, ICodexContracts contracts, IChainStateChangeHandler changeHandler, DateTime startUtc, bool doProofPeriodMonitoring)
|
||||
public ChainState(ILog log, IGethNode geth, ICodexContracts contracts, IChainStateChangeHandler changeHandler, DateTime startUtc, bool doProofPeriodMonitoring)
|
||||
{
|
||||
this.log = new LogPrefixer(log, "(ChainState) ");
|
||||
this.contracts = contracts;
|
||||
handler = changeHandler;
|
||||
this.doProofPeriodMonitoring = doProofPeriodMonitoring;
|
||||
TotalSpan = new TimeRange(startUtc, startUtc);
|
||||
PeriodMonitor = new PeriodMonitor(log, contracts);
|
||||
PeriodMonitor = new PeriodMonitor(log, contracts, geth);
|
||||
}
|
||||
|
||||
public TimeRange TotalSpan { get; private set; }
|
||||
|
||||
@ -1,7 +1,12 @@
|
||||
using Logging;
|
||||
using CodexContractsPlugin.Marketplace;
|
||||
using GethPlugin;
|
||||
using Logging;
|
||||
using Nethereum.Contracts;
|
||||
using Nethereum.Hex.HexConvertors.Extensions;
|
||||
using Nethereum.Model;
|
||||
using Utils;
|
||||
using Nethereum.RPC.Eth.DTOs;
|
||||
using Newtonsoft.Json;
|
||||
using System.Reflection;
|
||||
|
||||
namespace CodexContractsPlugin.ChainMonitor
|
||||
{
|
||||
@ -9,27 +14,29 @@ namespace CodexContractsPlugin.ChainMonitor
|
||||
{
|
||||
private readonly ILog log;
|
||||
private readonly ICodexContracts contracts;
|
||||
private readonly IGethNode geth;
|
||||
private readonly List<PeriodReport> reports = new List<PeriodReport>();
|
||||
private ulong? currentPeriod = null;
|
||||
private CurrentPeriod? currentPeriod = null;
|
||||
|
||||
public PeriodMonitor(ILog log, ICodexContracts contracts)
|
||||
public PeriodMonitor(ILog log, ICodexContracts contracts, IGethNode geth)
|
||||
{
|
||||
this.log = log;
|
||||
this.contracts = contracts;
|
||||
this.geth = geth;
|
||||
}
|
||||
|
||||
public void Update(DateTime eventUtc, IChainStateRequest[] requests)
|
||||
{
|
||||
var period = contracts.GetPeriodNumber(eventUtc);
|
||||
if (!currentPeriod.HasValue)
|
||||
var periodNumber = contracts.GetPeriodNumber(eventUtc);
|
||||
if (currentPeriod == null)
|
||||
{
|
||||
currentPeriod = period;
|
||||
currentPeriod = CreateCurrentPeriod(periodNumber, requests);
|
||||
return;
|
||||
}
|
||||
if (period == currentPeriod.Value) return;
|
||||
if (periodNumber == currentPeriod.PeriodNumber) return;
|
||||
|
||||
CreateReportForPeriod(currentPeriod.Value, requests);
|
||||
currentPeriod = period;
|
||||
CreateReportForPeriod(currentPeriod, requests);
|
||||
currentPeriod = CreateCurrentPeriod(periodNumber, requests);
|
||||
}
|
||||
|
||||
public PeriodMonitorResult GetAndClearReports()
|
||||
@ -39,26 +46,76 @@ namespace CodexContractsPlugin.ChainMonitor
|
||||
return new PeriodMonitorResult(result);
|
||||
}
|
||||
|
||||
private void CreateReportForPeriod(ulong periodNumber, IChainStateRequest[] requests)
|
||||
private CurrentPeriod CreateCurrentPeriod(ulong periodNumber, IChainStateRequest[] requests)
|
||||
{
|
||||
var result = new CurrentPeriod(periodNumber);
|
||||
ForEachActiveSlot(requests, (request, slotIndex) =>
|
||||
{
|
||||
if (contracts.IsProofRequired(request.RequestId, slotIndex))
|
||||
{
|
||||
var idx = Convert.ToInt32(slotIndex);
|
||||
var host = request.Hosts.GetHost(idx);
|
||||
if (host != null)
|
||||
{
|
||||
result.RequiredProofs.Add(new PeriodRequiredProof(host, request, idx));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void CreateReportForPeriod(CurrentPeriod currentPeriod, IChainStateRequest[] requests)
|
||||
{
|
||||
// Fetch function calls during period. Format report.
|
||||
var timeRange = contracts.GetPeriodTimeRange(currentPeriod.PeriodNumber);
|
||||
var blockRange = geth.ConvertTimeRangeToBlockRange(timeRange);
|
||||
|
||||
// MarkProofAsMissingFunction
|
||||
// SubmitProofFunction
|
||||
// FreeSlot1Function
|
||||
// FreeSlotFunction
|
||||
|
||||
var callReports = new List<FunctionCallReport>();
|
||||
geth.IterateTransactions(blockRange, (t, blkI, blkUtc) =>
|
||||
{
|
||||
CreateFunctionCallReport<MarkProofAsMissingFunction>(callReports, t, blkUtc);
|
||||
CreateFunctionCallReport<SubmitProofFunction>(callReports, t, blkUtc);
|
||||
CreateFunctionCallReport<FreeSlot1Function>(callReports, t, blkUtc);
|
||||
CreateFunctionCallReport<FreeSlotFunction>(callReports, t, blkUtc);
|
||||
});
|
||||
|
||||
var report = new PeriodReport(
|
||||
new ProofPeriod(
|
||||
currentPeriod.PeriodNumber,
|
||||
timeRange.From,
|
||||
timeRange.To),
|
||||
currentPeriod.RequiredProofs.ToArray(),
|
||||
callReports.ToArray());
|
||||
|
||||
report.Log(log);
|
||||
reports.Add(report);
|
||||
}
|
||||
|
||||
private void CreateFunctionCallReport<TFunc>(List<FunctionCallReport> reports, Transaction t, DateTime blockUtc) where TFunc : FunctionMessage, new()
|
||||
{
|
||||
if (t.IsTransactionForFunctionMessage<TFunc>())
|
||||
{
|
||||
var func = t.DecodeTransactionToFunctionMessage<TFunc>();
|
||||
|
||||
reports.Add(new FunctionCallReport(blockUtc, typeof(TFunc).Name, JsonConvert.SerializeObject(func)));
|
||||
}
|
||||
}
|
||||
|
||||
private void ForEachActiveSlot(IChainStateRequest[] requests, Action<IChainStateRequest, ulong> action)
|
||||
{
|
||||
ulong total = 0;
|
||||
var periodProofs = new List<PeriodProof>();
|
||||
foreach (var request in requests)
|
||||
{
|
||||
for (ulong slotIndex = 0; slotIndex < request.Request.Ask.Slots; slotIndex++)
|
||||
{
|
||||
var state = contracts.GetProofState(request.RequestId, slotIndex, periodNumber);
|
||||
|
||||
total++;
|
||||
var idx = Convert.ToInt32(slotIndex);
|
||||
var host = request.Hosts.GetHost(idx);
|
||||
var proof = new PeriodProof(host, request, idx, state);
|
||||
periodProofs.Add(proof);
|
||||
action(request, slotIndex);
|
||||
}
|
||||
}
|
||||
var report = new PeriodReport(periodNumber, total, periodProofs.ToArray());
|
||||
report.Log(log);
|
||||
reports.Add(report);
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,91 +124,19 @@ namespace CodexContractsPlugin.ChainMonitor
|
||||
public PeriodMonitorResult(PeriodReport[] reports)
|
||||
{
|
||||
Reports = reports;
|
||||
|
||||
CalcStats();
|
||||
}
|
||||
|
||||
public PeriodReport[] Reports { get; }
|
||||
|
||||
public bool IsEmpty { get; private set; }
|
||||
public ulong PeriodLow { get; private set; }
|
||||
public ulong PeriodHigh { get; private set; }
|
||||
public float AverageNumSlots { get; private set; }
|
||||
public float AverageNumProofsRequired { get; private set; }
|
||||
|
||||
private void CalcStats()
|
||||
{
|
||||
IsEmpty = Reports.All(r => r.PeriodProofs.Length == 0);
|
||||
if (Reports.Length == 0) return;
|
||||
|
||||
PeriodLow = Reports.Min(r => r.PeriodNumber);
|
||||
PeriodHigh = Reports.Max(r => r.PeriodNumber);
|
||||
AverageNumSlots = Reports.Average(r => Convert.ToSingle(r.TotalNumSlots));
|
||||
AverageNumProofsRequired = Reports.Average(r => Convert.ToSingle(r.PeriodProofs.Count(p => p.State != ProofState.NotRequired)));
|
||||
}
|
||||
}
|
||||
|
||||
public class PeriodReport
|
||||
public class CurrentPeriod
|
||||
{
|
||||
public PeriodReport(ulong periodNumber, ulong totalNumSlots, PeriodProof[] periodProofs)
|
||||
public CurrentPeriod(ulong periodNumber)
|
||||
{
|
||||
PeriodNumber = periodNumber;
|
||||
TotalNumSlots = totalNumSlots;
|
||||
PeriodProofs = periodProofs;
|
||||
}
|
||||
|
||||
public ulong PeriodNumber { get; }
|
||||
public ulong TotalNumSlots { get; }
|
||||
public PeriodProof[] PeriodProofs { get; }
|
||||
|
||||
public PeriodProof[] GetMissedProofs()
|
||||
{
|
||||
return PeriodProofs.Where(p => p.State == ProofState.MissedAndMarked || p.State == ProofState.MissedNotMarked).ToArray();
|
||||
}
|
||||
|
||||
public void Log(ILog log)
|
||||
{
|
||||
log.Log($"Period report: {PeriodNumber}");
|
||||
log.Log($" - Slots: {TotalNumSlots}");
|
||||
foreach (var p in PeriodProofs)
|
||||
{
|
||||
log.Log($" - {p.Describe()}");
|
||||
}
|
||||
}
|
||||
|
||||
private void Log(ILog log, PeriodProof[] proofs)
|
||||
{
|
||||
if (proofs.Length == 0) return;
|
||||
foreach (var p in proofs)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class PeriodProof
|
||||
{
|
||||
public PeriodProof(EthAddress? host, IChainStateRequest request, int slotIndex, ProofState state)
|
||||
{
|
||||
Host = host;
|
||||
Request = request;
|
||||
SlotIndex = slotIndex;
|
||||
State = state;
|
||||
}
|
||||
|
||||
public EthAddress? Host { get; }
|
||||
public IChainStateRequest Request { get; }
|
||||
public int SlotIndex { get; }
|
||||
public ProofState State { get; }
|
||||
|
||||
public string FormatHost()
|
||||
{
|
||||
if (Host == null) return "Unknown host";
|
||||
return Host.Address;
|
||||
}
|
||||
|
||||
public string Describe()
|
||||
{
|
||||
return $"{FormatHost()} - {Request.RequestId.ToHex()} slotIndex:{SlotIndex} => {State}";
|
||||
}
|
||||
public List<PeriodRequiredProof> RequiredProofs { get; } = new List<PeriodRequiredProof>();
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
using Logging;
|
||||
using Utils;
|
||||
|
||||
namespace CodexContractsPlugin.ChainMonitor
|
||||
{
|
||||
public class PeriodReport
|
||||
{
|
||||
public PeriodReport(ProofPeriod period, PeriodRequiredProof[] required, FunctionCallReport[] functionCalls)
|
||||
{
|
||||
Period = period;
|
||||
Required = required;
|
||||
FunctionCalls = functionCalls;
|
||||
}
|
||||
|
||||
public ProofPeriod Period { get; }
|
||||
public PeriodRequiredProof[] Required { get; }
|
||||
public FunctionCallReport[] FunctionCalls { get; }
|
||||
|
||||
public void Log(ILog log)
|
||||
{
|
||||
log.Log($"Period report: {Period}");
|
||||
foreach (var r in Required)
|
||||
{
|
||||
log.Log($" Required: {r.Describe()}");
|
||||
}
|
||||
log.Log(" - Calls:");
|
||||
foreach (var f in FunctionCalls)
|
||||
{
|
||||
log.Log($" - {f.Describe()}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class FunctionCallReport
|
||||
{
|
||||
public FunctionCallReport(DateTime utc, string name, string payload)
|
||||
{
|
||||
Utc = utc;
|
||||
Name = name;
|
||||
Payload = payload;
|
||||
}
|
||||
|
||||
public DateTime Utc { get; }
|
||||
public string Name { get; }
|
||||
public string Payload { get; }
|
||||
|
||||
public string Describe()
|
||||
{
|
||||
return $"[{Time.FormatTimestamp(Utc)}] {Name} = \"{Payload}\"";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
using Nethereum.Hex.HexConvertors.Extensions;
|
||||
using Utils;
|
||||
|
||||
namespace CodexContractsPlugin.ChainMonitor
|
||||
{
|
||||
public class PeriodRequiredProof
|
||||
{
|
||||
public PeriodRequiredProof(EthAddress host, IChainStateRequest request, int slotIndex)
|
||||
{
|
||||
Host = host;
|
||||
Request = request;
|
||||
SlotIndex = slotIndex;
|
||||
}
|
||||
|
||||
public EthAddress Host { get; }
|
||||
public IChainStateRequest Request { get; }
|
||||
public int SlotIndex { get; }
|
||||
|
||||
public string Describe()
|
||||
{
|
||||
return $"{Request.RequestId.ToHex()} slotIndex:{SlotIndex} by {Host}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
using Utils;
|
||||
|
||||
namespace CodexContractsPlugin.ChainMonitor
|
||||
{
|
||||
public class ProofPeriod
|
||||
{
|
||||
public ProofPeriod(ulong periodNumber, DateTime startUtc, DateTime endUtc)
|
||||
{
|
||||
PeriodNumber = periodNumber;
|
||||
StartUtc = startUtc;
|
||||
EndUtc = endUtc;
|
||||
}
|
||||
|
||||
public ulong PeriodNumber { get; }
|
||||
public DateTime StartUtc { get; }
|
||||
public DateTime EndUtc { get; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{PeriodNumber} - {Time.FormatTimestamp(StartUtc)} -> {Time.FormatTimestamp(EndUtc)}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -29,21 +29,14 @@ namespace CodexContractsPlugin
|
||||
RequestState GetRequestState(byte[] requestId);
|
||||
Request GetRequest(byte[] requestId);
|
||||
ulong GetPeriodNumber(DateTime utc);
|
||||
TimeRange GetPeriodTimeRange(ulong periodNumber);
|
||||
void WaitUntilNextPeriod();
|
||||
ProofState GetProofState(byte[] requestId, decimal slotIndex, ulong period);
|
||||
bool IsProofRequired(byte[] requestId, decimal slotIndex);
|
||||
byte[] GetSlotId(byte[] requestId, decimal slotIndex);
|
||||
|
||||
ICodexContracts WithDifferentGeth(IGethNode node);
|
||||
}
|
||||
|
||||
public enum ProofState
|
||||
{
|
||||
NotRequired,
|
||||
NotMissed,
|
||||
MissedNotMarked,
|
||||
MissedAndMarked,
|
||||
}
|
||||
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public enum RequestState
|
||||
{
|
||||
@ -155,6 +148,16 @@ namespace CodexContractsPlugin
|
||||
return Convert.ToUInt64(result);
|
||||
}
|
||||
|
||||
public TimeRange GetPeriodTimeRange(ulong periodNumber)
|
||||
{
|
||||
var periodSeconds = (ulong)Deployment.Config.Proofs.Period;
|
||||
var startUtco = Convert.ToInt64(periodSeconds * periodNumber);
|
||||
var endUtco = Convert.ToInt64(periodSeconds * (periodNumber + 1));
|
||||
var start = DateTimeOffset.FromUnixTimeSeconds(startUtco).UtcDateTime;
|
||||
var end = DateTimeOffset.FromUnixTimeSeconds(endUtco).UtcDateTime;
|
||||
return new TimeRange(start, end);
|
||||
}
|
||||
|
||||
public void WaitUntilNextPeriod()
|
||||
{
|
||||
var now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||
@ -163,14 +166,10 @@ namespace CodexContractsPlugin
|
||||
Thread.Sleep(TimeSpan.FromSeconds(secondsLeft + 1));
|
||||
}
|
||||
|
||||
public ProofState GetProofState(byte[] requestId, decimal slotIndex, ulong period)
|
||||
public bool IsProofRequired(byte[] requestId, decimal slotIndex)
|
||||
{
|
||||
var slotId = GetSlotId(requestId, slotIndex);
|
||||
|
||||
var required = IsProofRequired(slotId);
|
||||
if (!required) return ProofState.NotRequired;
|
||||
|
||||
return IsProofMissing(slotId, period);
|
||||
return IsProofRequired(slotId);
|
||||
}
|
||||
|
||||
public ICodexContracts WithDifferentGeth(IGethNode node)
|
||||
@ -199,72 +198,6 @@ namespace CodexContractsPlugin
|
||||
return result.ReturnValue1;
|
||||
}
|
||||
|
||||
private ProofState IsProofMissing(byte[] slotId, ulong period)
|
||||
{
|
||||
// In case of a missed proof, one of two things can be true:
|
||||
// 1 - The proof was missed but no validator marked it as missing:
|
||||
// We can see this by calling "canMarkProofAsMissing" and it returns true/doesn't throw.
|
||||
// 2 - The proof was missed and it was marked as missing by a validator:
|
||||
// We can see this by a successful call to "MarkProofAsMissing" on-chain.
|
||||
|
||||
if (CallCanMarkProofAsMissing(slotId, period))
|
||||
{
|
||||
return ProofState.MissedNotMarked;
|
||||
}
|
||||
if (WasMarkProofAsMissingCalled(slotId, period))
|
||||
{
|
||||
return ProofState.MissedAndMarked;
|
||||
}
|
||||
|
||||
return ProofState.NotMissed;
|
||||
}
|
||||
|
||||
private bool CallCanMarkProofAsMissing(byte[] slotId, ulong period)
|
||||
{
|
||||
try
|
||||
{
|
||||
var func = new CanMarkProofAsMissingFunction
|
||||
{
|
||||
SlotId = slotId,
|
||||
Period = period
|
||||
};
|
||||
|
||||
gethNode.Call<CanMarkProofAsMissingFunction>(Deployment.MarketplaceAddress, func);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (AggregateException exc)
|
||||
{
|
||||
if (exc.InnerExceptions.Count == 1)
|
||||
{
|
||||
if (exc.InnerExceptions[0].GetType() == typeof(SmartContractCustomErrorRevertException))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private bool WasMarkProofAsMissingCalled(byte[] slotId, ulong period)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
var currentPeriod = new TimeRange(now - Deployment.Config.PeriodDuration, now);
|
||||
var interval = gethNode.ConvertTimeRangeToBlockRange(currentPeriod);
|
||||
var slot = slotId.ToHex().ToLowerInvariant();
|
||||
|
||||
var found = false;
|
||||
gethNode.IterateFunctionCalls<MarkProofAsMissingFunction>(interval, (b, fn) =>
|
||||
{
|
||||
if (fn.Period == period && fn.SlotId.ToHex().ToLowerInvariant() == slot)
|
||||
{
|
||||
found = true;
|
||||
}
|
||||
});
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
private ContractInteractions StartInteraction()
|
||||
{
|
||||
return new ContractInteractions(log, gethNode);
|
||||
|
||||
@ -33,6 +33,7 @@ namespace GethPlugin
|
||||
List<EventLog<TEvent>> GetEvents<TEvent>(string address, TimeRange timeRange) where TEvent : IEventDTO, new();
|
||||
BlockInterval ConvertTimeRangeToBlockRange(TimeRange timeRange);
|
||||
BlockTimeEntry GetBlockForNumber(ulong number);
|
||||
void IterateTransactions(BlockInterval blockRange, Action<Transaction, ulong, DateTime> action);
|
||||
void IterateFunctionCalls<TFunc>(BlockInterval blockInterval, Action<BlockTimeEntry, TFunc> onCall) where TFunc : FunctionMessage, new();
|
||||
IGethNode WithDifferentAccount(EthAccount account);
|
||||
}
|
||||
@ -223,28 +224,37 @@ namespace GethPlugin
|
||||
return StartInteraction().GetBlockWithTransactions(number);
|
||||
}
|
||||
|
||||
public void IterateFunctionCalls<TFunc>(BlockInterval blockRange, Action<BlockTimeEntry, TFunc> onCall) where TFunc : FunctionMessage, new()
|
||||
public void IterateTransactions(BlockInterval blockRange, Action<Transaction, ulong, DateTime> action)
|
||||
{
|
||||
var i = StartInteraction();
|
||||
for (var blkI = blockRange.From; blkI <= blockRange.To; blkI++)
|
||||
{
|
||||
var blk = i.GetBlockWithTransactions(blkI);
|
||||
var blkUtc = DateTimeOffset.FromUnixTimeSeconds(blk.Timestamp.ToLong()).UtcDateTime;
|
||||
|
||||
foreach (var t in blk.Transactions)
|
||||
{
|
||||
if (t.IsTransactionForFunctionMessage<TFunc>())
|
||||
{
|
||||
var func = t.DecodeTransactionToFunctionMessage<TFunc>();
|
||||
if (func != null)
|
||||
{
|
||||
var b = GetBlockForNumber(blkI);
|
||||
onCall(b, func);
|
||||
}
|
||||
}
|
||||
action(t, blkI, blkUtc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void IterateFunctionCalls<TFunc>(BlockInterval blockRange, Action<BlockTimeEntry, TFunc> onCall) where TFunc : FunctionMessage, new()
|
||||
{
|
||||
IterateTransactions(blockRange, (t, blkI, blkUtc) =>
|
||||
{
|
||||
if (t.IsTransactionForFunctionMessage<TFunc>())
|
||||
{
|
||||
var func = t.DecodeTransactionToFunctionMessage<TFunc>();
|
||||
if (func != null)
|
||||
{
|
||||
var b = GetBlockForNumber(blkI);
|
||||
onCall(b, func);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected abstract NethereumInteraction StartInteraction();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
using CodexContractsPlugin;
|
||||
using CodexContractsPlugin.ChainMonitor;
|
||||
using GethPlugin;
|
||||
using Logging;
|
||||
using Utils;
|
||||
|
||||
@ -8,20 +9,22 @@ namespace CodexReleaseTests.Utils
|
||||
public class ChainMonitor
|
||||
{
|
||||
private readonly ILog log;
|
||||
private readonly IGethNode gethNode;
|
||||
private readonly ICodexContracts contracts;
|
||||
private readonly DateTime startUtc;
|
||||
private readonly TimeSpan updateInterval;
|
||||
private CancellationTokenSource cts = new CancellationTokenSource();
|
||||
private Task worker = Task.CompletedTask;
|
||||
|
||||
public ChainMonitor(ILog log, ICodexContracts contracts, DateTime startUtc)
|
||||
: this(log, contracts, startUtc, TimeSpan.FromSeconds(3.0))
|
||||
public ChainMonitor(ILog log, IGethNode gethNode, ICodexContracts contracts, DateTime startUtc)
|
||||
: this(log, gethNode, contracts, startUtc, TimeSpan.FromSeconds(3.0))
|
||||
{
|
||||
}
|
||||
|
||||
public ChainMonitor(ILog log, ICodexContracts contracts, DateTime startUtc, TimeSpan updateInterval)
|
||||
public ChainMonitor(ILog log, IGethNode gethNode, ICodexContracts contracts, DateTime startUtc, TimeSpan updateInterval)
|
||||
{
|
||||
this.log = log;
|
||||
this.gethNode = gethNode;
|
||||
this.contracts = contracts;
|
||||
this.startUtc = startUtc;
|
||||
this.updateInterval = updateInterval;
|
||||
@ -42,7 +45,7 @@ namespace CodexReleaseTests.Utils
|
||||
|
||||
private void Worker(Action onFailure)
|
||||
{
|
||||
var state = new ChainState(log, contracts, new DoNothingThrowingChainEventHandler(), startUtc, doProofPeriodMonitoring: true);
|
||||
var state = new ChainState(log, gethNode, contracts, new DoNothingThrowingChainEventHandler(), startUtc, doProofPeriodMonitoring: true);
|
||||
Thread.Sleep(updateInterval);
|
||||
|
||||
log.Log($"Chain monitoring started. Update interval: {Time.FormatDuration(updateInterval)}");
|
||||
@ -66,15 +69,6 @@ namespace CodexReleaseTests.Utils
|
||||
private void UpdateChainState(ChainState state)
|
||||
{
|
||||
state.Update();
|
||||
|
||||
var reports = state.PeriodMonitor.GetAndClearReports();
|
||||
if (reports.IsEmpty) return;
|
||||
|
||||
var slots = reports.Reports.Sum(r => Convert.ToInt32(r.TotalNumSlots));
|
||||
var required = reports.Reports.Sum(r => Convert.ToInt32(r.PeriodProofs.Count(p => p.State != ProofState.NotRequired)));
|
||||
var missed = reports.Reports.Sum(r => r.GetMissedProofs().Length);
|
||||
|
||||
log.Log($"Proof report: Slots={slots} Required={required} Missed={missed}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@ namespace CodexReleaseTests.Utils
|
||||
{
|
||||
var geth = StartGethNode(s => s.IsMiner());
|
||||
var contracts = Ci.StartCodexContracts(geth, BootstrapNode.Version);
|
||||
var monitor = SetupChainMonitor(GetTestLog(), contracts, GetTestRunTimeRange().From);
|
||||
var monitor = SetupChainMonitor(GetTestLog(), geth, contracts, GetTestRunTimeRange().From);
|
||||
handle = new MarketplaceHandle(geth, contracts, monitor);
|
||||
}
|
||||
|
||||
@ -169,11 +169,11 @@ namespace CodexReleaseTests.Utils
|
||||
});
|
||||
}
|
||||
|
||||
private ChainMonitor? SetupChainMonitor(ILog log, ICodexContracts contracts, DateTime startUtc)
|
||||
private ChainMonitor? SetupChainMonitor(ILog log, IGethNode gethNode, ICodexContracts contracts, DateTime startUtc)
|
||||
{
|
||||
if (!MonitorChainState) return null;
|
||||
|
||||
var result = new ChainMonitor(log, contracts, startUtc);
|
||||
var result = new ChainMonitor(log, gethNode, contracts, startUtc);
|
||||
result.Start(() =>
|
||||
{
|
||||
Assert.Fail("Failure in chain monitor.");
|
||||
|
||||
@ -91,7 +91,8 @@ namespace DistTestCore
|
||||
return Path.Join(
|
||||
config.LogRoot,
|
||||
$"{start.Year}-{Pad(start.Month)}",
|
||||
Pad(start.Day));
|
||||
Pad(start.Day),
|
||||
$"{Pad(start.Hour)}-{Pad(start.Minute)}-{Pad(start.Second)}");
|
||||
}
|
||||
|
||||
private static string Pad(int n)
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
using CodexContractsPlugin;
|
||||
using CodexContractsPlugin.ChainMonitor;
|
||||
using GethPlugin;
|
||||
using TestNetRewarder;
|
||||
using Utils;
|
||||
|
||||
@ -13,11 +14,11 @@ namespace MarketInsights
|
||||
private readonly int maxContributions;
|
||||
private readonly ChainState chainState;
|
||||
|
||||
public AverageHistory(AppState appState, ICodexContracts contracts, int maxContributions)
|
||||
public AverageHistory(AppState appState, IGethNode geth, ICodexContracts contracts, int maxContributions)
|
||||
{
|
||||
this.appState = appState;
|
||||
this.maxContributions = maxContributions;
|
||||
chainState = new ChainState(appState.Log, contracts, mux, appState.Config.HistoryStartUtc,
|
||||
chainState = new ChainState(appState.Log, geth, contracts, mux, appState.Config.HistoryStartUtc,
|
||||
doProofPeriodMonitoring: false);
|
||||
}
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ namespace MarketInsights
|
||||
var connector = GethConnector.GethConnector.Initialize(appState.Log);
|
||||
if (connector == null) throw new Exception("Invalid Geth information");
|
||||
|
||||
var updater = new Updater(appState, connector.CodexContracts, cts.Token);
|
||||
var updater = new Updater(appState, connector.GethNode, connector.CodexContracts, cts.Token);
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using CodexContractsPlugin;
|
||||
using GethPlugin;
|
||||
using TestNetRewarder;
|
||||
|
||||
namespace MarketInsights
|
||||
@ -11,13 +12,13 @@ namespace MarketInsights
|
||||
private readonly Tracker[] trackers;
|
||||
private readonly AverageHistory averageHistory;
|
||||
|
||||
public Updater(AppState appState, ICodexContracts contracts, CancellationToken ct)
|
||||
public Updater(AppState appState, IGethNode geth, ICodexContracts contracts, CancellationToken ct)
|
||||
{
|
||||
this.appState = appState;
|
||||
this.ct = ct;
|
||||
|
||||
trackers = CreateTrackers();
|
||||
averageHistory = new AverageHistory(appState, contracts, trackers.Max(t => t.NumberOfSegments));
|
||||
averageHistory = new AverageHistory(appState, geth, contracts, trackers.Max(t => t.NumberOfSegments));
|
||||
}
|
||||
|
||||
private Tracker[] CreateTrackers()
|
||||
|
||||
@ -123,17 +123,18 @@ namespace TestNetRewarder
|
||||
|
||||
public void ProcessPeriodReports(PeriodMonitorResult reports)
|
||||
{
|
||||
if (reports.IsEmpty) return;
|
||||
//if (reports.IsEmpty) return;
|
||||
|
||||
var lines = new List<string> {
|
||||
$"Periods: [{reports.PeriodLow} ... {reports.PeriodHigh}]",
|
||||
$"Average number of slots: {reports.AverageNumSlots.ToString("F2")}",
|
||||
$"Average number of proofs required: {reports.AverageNumProofsRequired.ToString("F2")}"
|
||||
};
|
||||
//var lines = new List<string> {
|
||||
// $"Periods: [{reports.PeriodLow} ... {reports.PeriodHigh}]",
|
||||
// $"Average number of slots: {reports.AverageNumSlots.ToString("F2")}",
|
||||
// $"Average number of proofs required: {reports.AverageNumProofsRequired.ToString("F2")}"
|
||||
//};
|
||||
|
||||
AddMissedProofDetails(lines, reports.Reports);
|
||||
// AddMissedProofDetails(lines, reports.Reports);
|
||||
// todo!
|
||||
|
||||
AddBlock(0, $"{emojiMaps.ProofReport} **Proof system report**", lines.ToArray());
|
||||
//AddBlock(0, $"{emojiMaps.ProofReport} **Proof system report**", lines.ToArray());
|
||||
}
|
||||
|
||||
private string GetSlotFilledIcon(bool isRepair)
|
||||
@ -148,40 +149,40 @@ namespace TestNetRewarder
|
||||
return $"Slot Filled";
|
||||
}
|
||||
|
||||
private void AddMissedProofDetails(List<string> lines, PeriodReport[] reports)
|
||||
{
|
||||
var reportsWithMissedProofs = reports.Where(r => r.GetMissedProofs().Any()).ToArray();
|
||||
if (reportsWithMissedProofs.Length < 1)
|
||||
{
|
||||
lines.Add($"No proofs were missed {emojiMaps.NoProofsMissed}");
|
||||
return;
|
||||
}
|
||||
//private void AddMissedProofDetails(List<string> lines, PeriodReport[] reports)
|
||||
//{
|
||||
// var reportsWithMissedProofs = reports.Where(r => r.GetMissedProofs().Any()).ToArray();
|
||||
// if (reportsWithMissedProofs.Length < 1)
|
||||
// {
|
||||
// lines.Add($"No proofs were missed {emojiMaps.NoProofsMissed}");
|
||||
// return;
|
||||
// }
|
||||
|
||||
var totalMissed = reportsWithMissedProofs.Sum(r => r.GetMissedProofs().Length);
|
||||
if (totalMissed > 10)
|
||||
{
|
||||
lines.Add($"[{totalMissed}] proofs were missed {emojiMaps.ManyProofsMissed}");
|
||||
return;
|
||||
}
|
||||
// var totalMissed = reportsWithMissedProofs.Sum(r => r.GetMissedProofs().Length);
|
||||
// if (totalMissed > 10)
|
||||
// {
|
||||
// lines.Add($"[{totalMissed}] proofs were missed {emojiMaps.ManyProofsMissed}");
|
||||
// return;
|
||||
// }
|
||||
|
||||
foreach (var report in reportsWithMissedProofs)
|
||||
{
|
||||
DescribeMissedProof(lines, report);
|
||||
}
|
||||
}
|
||||
// foreach (var report in reportsWithMissedProofs)
|
||||
// {
|
||||
// DescribeMissedProof(lines, report);
|
||||
// }
|
||||
//}
|
||||
|
||||
private void DescribeMissedProof(List<string> lines, PeriodReport report)
|
||||
{
|
||||
foreach (var missedProof in report.GetMissedProofs())
|
||||
{
|
||||
DescribeMissedProof(lines, missedProof);
|
||||
}
|
||||
}
|
||||
//private void DescribeMissedProof(List<string> lines, PeriodReport report)
|
||||
//{
|
||||
// foreach (var missedProof in report.GetMissedProofs())
|
||||
// {
|
||||
// DescribeMissedProof(lines, missedProof);
|
||||
// }
|
||||
//}
|
||||
|
||||
private void DescribeMissedProof(List<string> lines, PeriodProof missedProof)
|
||||
{
|
||||
lines.Add($"[{missedProof.FormatHost()}] missed proof for {FormatRequestId(missedProof.Request)} (slotIndex: {missedProof.SlotIndex})");
|
||||
}
|
||||
//private void DescribeMissedProof(List<string> lines, PeriodRequiredProof missedProof)
|
||||
//{
|
||||
// lines.Add($"[{missedProof.FormatHost()}] missed proof for {FormatRequestId(missedProof.Request)} (slotIndex: {missedProof.SlotIndex})");
|
||||
//}
|
||||
|
||||
private void AddRequestBlock(RequestEvent requestEvent, string icon, string eventName, params string[] content)
|
||||
{
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
using CodexContractsPlugin;
|
||||
using CodexContractsPlugin.ChainMonitor;
|
||||
using GethPlugin;
|
||||
using Logging;
|
||||
using Utils;
|
||||
|
||||
@ -15,7 +16,7 @@ namespace TestNetRewarder
|
||||
private readonly ILog log;
|
||||
private DateTime lastPeriodUpdateUtc;
|
||||
|
||||
public Processor(Configuration config, BotClient client, ICodexContracts contracts, ILog log)
|
||||
public Processor(Configuration config, BotClient client, IGethNode geth, ICodexContracts contracts, ILog log)
|
||||
{
|
||||
this.config = config;
|
||||
this.client = client;
|
||||
@ -27,7 +28,7 @@ namespace TestNetRewarder
|
||||
builder = new RequestBuilder();
|
||||
eventsFormatter = new EventsFormatter(config, contracts.Deployment.Config);
|
||||
|
||||
chainState = new ChainState(log, contracts, eventsFormatter, config.HistoryStartUtc,
|
||||
chainState = new ChainState(log, geth, contracts, eventsFormatter, config.HistoryStartUtc,
|
||||
doProofPeriodMonitoring: config.ShowProofPeriodReports > 0);
|
||||
}
|
||||
|
||||
|
||||
@ -31,7 +31,7 @@ namespace TestNetRewarder
|
||||
if (connector == null) throw new Exception("Invalid Geth information");
|
||||
|
||||
BotClient = new BotClient(Config, Log);
|
||||
processor = new Processor(Config, BotClient, connector.CodexContracts, Log);
|
||||
processor = new Processor(Config, BotClient, connector.GethNode, connector.CodexContracts, Log);
|
||||
|
||||
EnsurePath(Config.DataPath);
|
||||
EnsurePath(Config.LogPath);
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
using CodexContractsPlugin;
|
||||
using CodexContractsPlugin.ChainMonitor;
|
||||
using CodexContractsPlugin.Marketplace;
|
||||
using GethPlugin;
|
||||
using Logging;
|
||||
using Nethereum.Hex.HexConvertors.Extensions;
|
||||
using Nethereum.Model;
|
||||
@ -11,13 +12,15 @@ namespace TraceContract
|
||||
public class ChainTracer
|
||||
{
|
||||
private readonly ILog log;
|
||||
private readonly IGethNode geth;
|
||||
private readonly ICodexContracts contracts;
|
||||
private readonly Input input;
|
||||
private readonly Output output;
|
||||
|
||||
public ChainTracer(ILog log, ICodexContracts contracts, Input input, Output output)
|
||||
public ChainTracer(ILog log, IGethNode geth, ICodexContracts contracts, Input input, Output output)
|
||||
{
|
||||
this.log = log;
|
||||
this.geth = geth;
|
||||
this.contracts = contracts;
|
||||
this.input = input;
|
||||
this.output = output;
|
||||
@ -60,7 +63,7 @@ namespace TraceContract
|
||||
var utc = request.Block.Utc.AddMinutes(-1.0);
|
||||
var tracker = new ChainRequestTracker(output, input.PurchaseId);
|
||||
var ignoreLog = new NullLog();
|
||||
var chainState = new ChainState(ignoreLog, contracts, tracker, utc, false);
|
||||
var chainState = new ChainState(ignoreLog, geth, contracts, tracker, utc, false);
|
||||
|
||||
var atNow = false;
|
||||
while (!tracker.IsFinished && !atNow)
|
||||
|
||||
@ -47,9 +47,10 @@ namespace TraceContract
|
||||
var entryPoint = new EntryPoint(log, new KubernetesWorkflow.Configuration(null, TimeSpan.FromMinutes(1.0), TimeSpan.FromSeconds(10.0), "_Unused!_"), Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));
|
||||
entryPoint.Announce();
|
||||
var ci = entryPoint.CreateInterface();
|
||||
var contracts = ConnectCodexContracts(ci);
|
||||
var geth = ConnectGethNode();
|
||||
var contracts = ConnectCodexContracts(ci, geth);
|
||||
|
||||
var chainTracer = new ChainTracer(log, contracts, input, output);
|
||||
var chainTracer = new ChainTracer(log, geth, contracts, input, output);
|
||||
var requestTimeRange = chainTracer.TraceChainTimeline();
|
||||
|
||||
Log("Downloading storage nodes logs for the request timerange...");
|
||||
@ -61,12 +62,15 @@ namespace TraceContract
|
||||
Log("Done");
|
||||
}
|
||||
|
||||
private ICodexContracts ConnectCodexContracts(CoreInterface ci)
|
||||
private IGethNode ConnectGethNode()
|
||||
{
|
||||
var account = EthAccountGenerator.GenerateNew();
|
||||
var blockCache = new BlockCache();
|
||||
var geth = new CustomGethNode(log, blockCache, config.RpcEndpoint, config.GethPort, account.PrivateKey);
|
||||
return new CustomGethNode(log, blockCache, config.RpcEndpoint, config.GethPort, account.PrivateKey);
|
||||
}
|
||||
|
||||
private ICodexContracts ConnectCodexContracts(CoreInterface ci, IGethNode geth)
|
||||
{
|
||||
var deployment = new CodexContractsDeployment(
|
||||
config: new MarketplaceConfig(),
|
||||
marketplaceAddress: config.MarketplaceAddress,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user