This commit is contained in:
Ben 2025-08-15 12:02:33 +02:00
parent 62f7d65c2d
commit 4e093f12d7
No known key found for this signature in database
GPG Key ID: 0F16E812E736C24B
18 changed files with 294 additions and 260 deletions

View File

@ -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; }

View File

@ -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>();
}
}

View File

@ -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}\"";
}
}
}

View File

@ -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}";
}
}
}

View File

@ -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)}";
}
}
}

View File

@ -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);

View File

@ -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();
}
}

View File

@ -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}");
}
}
}

View File

@ -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.");

View File

@ -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)

View File

@ -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);
}

View File

@ -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);

View File

@ -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()

View File

@ -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)
{

View File

@ -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);
}

View File

@ -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);

View File

@ -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)

View File

@ -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,