From 25a7a307933fe5adada74953a82b18abee40ee18 Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 5 Mar 2025 09:57:25 +0100 Subject: [PATCH] Better proof period reporting. Default proofSubmitted events to OFF. --- .../ChainMonitor/PeriodMonitor.cs | 44 +++++++++++- Tools/TestNetRewarder/Configuration.cs | 2 +- Tools/TestNetRewarder/EmojiMaps.cs | 2 + Tools/TestNetRewarder/EventsFormatter.cs | 72 +++++++++++++++---- 4 files changed, 103 insertions(+), 17 deletions(-) diff --git a/ProjectPlugins/CodexContractsPlugin/ChainMonitor/PeriodMonitor.cs b/ProjectPlugins/CodexContractsPlugin/ChainMonitor/PeriodMonitor.cs index 5ec8f5d0..5e8b0c7c 100644 --- a/ProjectPlugins/CodexContractsPlugin/ChainMonitor/PeriodMonitor.cs +++ b/ProjectPlugins/CodexContractsPlugin/ChainMonitor/PeriodMonitor.cs @@ -30,11 +30,11 @@ namespace CodexContractsPlugin.ChainMonitor currentPeriod = period; } - public PeriodReport[] GetAndClearReports() + public PeriodMonitorResult GetAndClearReports() { var result = reports.ToArray(); reports.Clear(); - return result; + return new PeriodMonitorResult(result); } private void CreateReportForPeriod(ulong lastBlockInPeriod, ulong periodNumber, IChainStateRequest[] requests) @@ -67,6 +67,46 @@ namespace CodexContractsPlugin.ChainMonitor } } + public class PeriodMonitorResult + { + 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 = true; + PeriodLow = ulong.MaxValue; + PeriodHigh = ulong.MinValue; + AverageNumSlots = 0.0f; + AverageNumProofsRequired = 0.0f; + float count = Reports.Length; + + foreach (var report in Reports) + { + if (report.TotalProofsRequired > 0) IsEmpty = false; + PeriodLow = Math.Min(PeriodLow, report.PeriodNumber); + PeriodHigh = Math.Min(PeriodHigh, report.PeriodNumber); + AverageNumSlots += Convert.ToSingle(report.TotalNumSlots); + AverageNumProofsRequired += Convert.ToSingle(report.TotalProofsRequired); + } + + AverageNumSlots = AverageNumSlots / count; + AverageNumProofsRequired = AverageNumProofsRequired / count; + } + } + public class PeriodReport { public PeriodReport(ulong periodNumber, ulong totalNumSlots, ulong totalProofsRequired, PeriodProofMissed[] missedProofs) diff --git a/Tools/TestNetRewarder/Configuration.cs b/Tools/TestNetRewarder/Configuration.cs index 6eef2624..5dbeac30 100644 --- a/Tools/TestNetRewarder/Configuration.cs +++ b/Tools/TestNetRewarder/Configuration.cs @@ -31,7 +31,7 @@ namespace TestNetRewarder public int ShowProofPeriodReports { get; set; } = 1; [Uniform("proof-submitted-events", "pse", "PROOFSUBMITTEDEVENTS", false, "When greater than zero, chain event summary will include proof-submitted events.")] - public int ShowProofSubmittedEvents { get; set; } = 1; + public int ShowProofSubmittedEvents { get; set; } = 0; // Defaulted to zero, aprox 7 to 10 such events every 2 minutes in testnet (from autoclient alone!) public string LogPath { diff --git a/Tools/TestNetRewarder/EmojiMaps.cs b/Tools/TestNetRewarder/EmojiMaps.cs index 5b5c3719..2cbb4e0e 100644 --- a/Tools/TestNetRewarder/EmojiMaps.cs +++ b/Tools/TestNetRewarder/EmojiMaps.cs @@ -85,6 +85,8 @@ public string Failed => "❌"; public string ProofSubmitted => "🎵"; public string ProofReport => "🔎"; + public string NoProofsMissed => "🏛"; + public string ManyProofsMissed => "😱"; public string StringToEmojis(string input, int outLength) { diff --git a/Tools/TestNetRewarder/EventsFormatter.cs b/Tools/TestNetRewarder/EventsFormatter.cs index 9ac117d9..388515d3 100644 --- a/Tools/TestNetRewarder/EventsFormatter.cs +++ b/Tools/TestNetRewarder/EventsFormatter.cs @@ -118,26 +118,60 @@ namespace TestNetRewarder errors.Add(msg); } - public void ProcessPeriodReports(PeriodReport[] periodReports) + public void ProcessPeriodReports(PeriodMonitorResult reports) { - var lines = periodReports.Select(FormatPeriodReport).ToList(); - lines.Insert(0, FormatPeriodReportLine("period", "totalSlots", "required", "missed")); + if (reports.IsEmpty) return; + + var lines = new List { + $"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); + AddBlock(0, $"{emojiMaps.ProofReport} **Proof system report**", lines.ToArray()); } - private string FormatPeriodReport(PeriodReport report) + private void AddMissedProofDetails(List lines, PeriodReport[] reports) { - return FormatPeriodReportLine( - periodNumber: report.PeriodNumber.ToString(), - totalSlots: report.TotalNumSlots.ToString(), - totalRequired: report.TotalProofsRequired.ToString(), - totalMissed: report.MissedProofs.Length.ToString() - ); + var reportsWithMissedProofs = reports.Where(r => r.MissedProofs.Length > 0).ToArray(); + if (reportsWithMissedProofs.Length < 1) + { + lines.Add($"No proofs were missed {emojiMaps.NoProofsMissed}"); + return; + } + + var totalMissed = reportsWithMissedProofs.Sum(r => r.MissedProofs.Length); + if (totalMissed > 10) + { + lines.Add($"[{totalMissed}] proofs were missed {emojiMaps.ManyProofsMissed}"); + return; + } + + foreach (var report in reportsWithMissedProofs) + { + DescribeMissedProof(lines, report); + } } - private string FormatPeriodReportLine(string periodNumber, string totalSlots, string totalRequired, string totalMissed) + private void DescribeMissedProof(List lines, PeriodReport report) { - return $"{periodNumber.PadLeft(10)} {totalSlots.PadLeft(10)} {totalRequired.PadLeft(10)} {totalMissed.PadLeft(10)}"; + foreach (var missedProof in report.MissedProofs) + { + DescribeMissedProof(lines, missedProof); + } + } + + private void DescribeMissedProof(List lines, PeriodProofMissed missedProof) + { + lines.Add($"[{FormatHost(missedProof.Host)}] missed proof for {FormatRequestId(missedProof.Request)} (slotIndex: {missedProof.SlotIndex})"); + } + + private string FormatHost(EthAddress? host) + { + if (host == null) return "Unknown host"; + return host.Address; } private void AddRequestBlock(RequestEvent requestEvent, string eventName, params string[] content) @@ -189,10 +223,20 @@ namespace TestNetRewarder } private string FormatRequestId(RequestEvent requestEvent) + { + return FormatRequestId(requestEvent.Request); + } + + private string FormatRequestId(IChainStateRequest request) + { + return FormatRequestId(request.Request.Id); + } + + private string FormatRequestId(string id) { return - $"({emojiMaps.StringToEmojis(requestEvent.Request.Request.Id, 3)})" + - $"`{requestEvent.Request.Request.Id}`"; + $"({emojiMaps.StringToEmojis(id, 3)})" + + $"`{id}`"; } private string BytesToHexString(byte[] bytes)