From 4e093f12d7bcd3ba4043b1e5c901be59c883ebe3 Mon Sep 17 00:00:00 2001 From: Ben Date: Fri, 15 Aug 2025 12:02:33 +0200 Subject: [PATCH] wip --- .../ChainMonitor/ChainState.cs | 5 +- .../ChainMonitor/PeriodMonitor.cs | 181 ++++++++---------- .../ChainMonitor/PeriodReport.cs | 52 +++++ .../ChainMonitor/PeriodRequiredProof.cs | 24 +++ .../ChainMonitor/ProofPeriod.cs | 23 +++ .../CodexContractsAccess.cs | 95 ++------- ProjectPlugins/GethPlugin/GethNode.cs | 30 ++- Tests/CodexReleaseTests/Utils/ChainMonitor.cs | 20 +- .../Utils/MarketplaceAutoBootstrapDistTest.cs | 6 +- Tests/DistTestCore/NameUtils.cs | 3 +- Tools/MarketInsights/AverageHistory.cs | 5 +- Tools/MarketInsights/Program.cs | 2 +- Tools/MarketInsights/Updater.cs | 5 +- Tools/TestNetRewarder/EventsFormatter.cs | 77 ++++---- Tools/TestNetRewarder/Processor.cs | 5 +- Tools/TestNetRewarder/Program.cs | 2 +- Tools/TraceContract/ChainTracer.cs | 7 +- Tools/TraceContract/Program.cs | 12 +- 18 files changed, 294 insertions(+), 260 deletions(-) create mode 100644 ProjectPlugins/CodexContractsPlugin/ChainMonitor/PeriodReport.cs create mode 100644 ProjectPlugins/CodexContractsPlugin/ChainMonitor/PeriodRequiredProof.cs create mode 100644 ProjectPlugins/CodexContractsPlugin/ChainMonitor/ProofPeriod.cs diff --git a/ProjectPlugins/CodexContractsPlugin/ChainMonitor/ChainState.cs b/ProjectPlugins/CodexContractsPlugin/ChainMonitor/ChainState.cs index 04d8e0e2..16c9e100 100644 --- a/ProjectPlugins/CodexContractsPlugin/ChainMonitor/ChainState.cs +++ b/ProjectPlugins/CodexContractsPlugin/ChainMonitor/ChainState.cs @@ -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; } diff --git a/ProjectPlugins/CodexContractsPlugin/ChainMonitor/PeriodMonitor.cs b/ProjectPlugins/CodexContractsPlugin/ChainMonitor/PeriodMonitor.cs index d1e469a8..61ba5ecd 100644 --- a/ProjectPlugins/CodexContractsPlugin/ChainMonitor/PeriodMonitor.cs +++ b/ProjectPlugins/CodexContractsPlugin/ChainMonitor/PeriodMonitor.cs @@ -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 reports = new List(); - 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(); + geth.IterateTransactions(blockRange, (t, blkI, blkUtc) => + { + CreateFunctionCallReport(callReports, t, blkUtc); + CreateFunctionCallReport(callReports, t, blkUtc); + CreateFunctionCallReport(callReports, t, blkUtc); + CreateFunctionCallReport(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(List reports, Transaction t, DateTime blockUtc) where TFunc : FunctionMessage, new() + { + if (t.IsTransactionForFunctionMessage()) + { + var func = t.DecodeTransactionToFunctionMessage(); + + reports.Add(new FunctionCallReport(blockUtc, typeof(TFunc).Name, JsonConvert.SerializeObject(func))); + } + } + + private void ForEachActiveSlot(IChainStateRequest[] requests, Action action) { - ulong total = 0; - var periodProofs = new List(); 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 RequiredProofs { get; } = new List(); } } diff --git a/ProjectPlugins/CodexContractsPlugin/ChainMonitor/PeriodReport.cs b/ProjectPlugins/CodexContractsPlugin/ChainMonitor/PeriodReport.cs new file mode 100644 index 00000000..0e2f6dc3 --- /dev/null +++ b/ProjectPlugins/CodexContractsPlugin/ChainMonitor/PeriodReport.cs @@ -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}\""; + } + } +} diff --git a/ProjectPlugins/CodexContractsPlugin/ChainMonitor/PeriodRequiredProof.cs b/ProjectPlugins/CodexContractsPlugin/ChainMonitor/PeriodRequiredProof.cs new file mode 100644 index 00000000..f8df4e23 --- /dev/null +++ b/ProjectPlugins/CodexContractsPlugin/ChainMonitor/PeriodRequiredProof.cs @@ -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}"; + } + } +} diff --git a/ProjectPlugins/CodexContractsPlugin/ChainMonitor/ProofPeriod.cs b/ProjectPlugins/CodexContractsPlugin/ChainMonitor/ProofPeriod.cs new file mode 100644 index 00000000..ca428170 --- /dev/null +++ b/ProjectPlugins/CodexContractsPlugin/ChainMonitor/ProofPeriod.cs @@ -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)}"; + } + } +} diff --git a/ProjectPlugins/CodexContractsPlugin/CodexContractsAccess.cs b/ProjectPlugins/CodexContractsPlugin/CodexContractsAccess.cs index 17a8c36c..132451e7 100644 --- a/ProjectPlugins/CodexContractsPlugin/CodexContractsAccess.cs +++ b/ProjectPlugins/CodexContractsPlugin/CodexContractsAccess.cs @@ -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(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(interval, (b, fn) => - { - if (fn.Period == period && fn.SlotId.ToHex().ToLowerInvariant() == slot) - { - found = true; - } - }); - - return found; - } - private ContractInteractions StartInteraction() { return new ContractInteractions(log, gethNode); diff --git a/ProjectPlugins/GethPlugin/GethNode.cs b/ProjectPlugins/GethPlugin/GethNode.cs index 15fa0d4e..04653efe 100644 --- a/ProjectPlugins/GethPlugin/GethNode.cs +++ b/ProjectPlugins/GethPlugin/GethNode.cs @@ -33,6 +33,7 @@ namespace GethPlugin List> GetEvents(string address, TimeRange timeRange) where TEvent : IEventDTO, new(); BlockInterval ConvertTimeRangeToBlockRange(TimeRange timeRange); BlockTimeEntry GetBlockForNumber(ulong number); + void IterateTransactions(BlockInterval blockRange, Action action); void IterateFunctionCalls(BlockInterval blockInterval, Action onCall) where TFunc : FunctionMessage, new(); IGethNode WithDifferentAccount(EthAccount account); } @@ -223,28 +224,37 @@ namespace GethPlugin return StartInteraction().GetBlockWithTransactions(number); } - public void IterateFunctionCalls(BlockInterval blockRange, Action onCall) where TFunc : FunctionMessage, new() + public void IterateTransactions(BlockInterval blockRange, Action 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()) - { - var func = t.DecodeTransactionToFunctionMessage(); - if (func != null) - { - var b = GetBlockForNumber(blkI); - onCall(b, func); - } - } + action(t, blkI, blkUtc); } } } + public void IterateFunctionCalls(BlockInterval blockRange, Action onCall) where TFunc : FunctionMessage, new() + { + IterateTransactions(blockRange, (t, blkI, blkUtc) => + { + if (t.IsTransactionForFunctionMessage()) + { + var func = t.DecodeTransactionToFunctionMessage(); + if (func != null) + { + var b = GetBlockForNumber(blkI); + onCall(b, func); + } + } + }); + } + protected abstract NethereumInteraction StartInteraction(); } } diff --git a/Tests/CodexReleaseTests/Utils/ChainMonitor.cs b/Tests/CodexReleaseTests/Utils/ChainMonitor.cs index 8723246b..f34081e0 100644 --- a/Tests/CodexReleaseTests/Utils/ChainMonitor.cs +++ b/Tests/CodexReleaseTests/Utils/ChainMonitor.cs @@ -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}"); } } } diff --git a/Tests/CodexReleaseTests/Utils/MarketplaceAutoBootstrapDistTest.cs b/Tests/CodexReleaseTests/Utils/MarketplaceAutoBootstrapDistTest.cs index 42bc03fa..f3dbdaa3 100644 --- a/Tests/CodexReleaseTests/Utils/MarketplaceAutoBootstrapDistTest.cs +++ b/Tests/CodexReleaseTests/Utils/MarketplaceAutoBootstrapDistTest.cs @@ -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."); diff --git a/Tests/DistTestCore/NameUtils.cs b/Tests/DistTestCore/NameUtils.cs index 10a4c498..76ea210e 100644 --- a/Tests/DistTestCore/NameUtils.cs +++ b/Tests/DistTestCore/NameUtils.cs @@ -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) diff --git a/Tools/MarketInsights/AverageHistory.cs b/Tools/MarketInsights/AverageHistory.cs index 4baebd3b..412846d0 100644 --- a/Tools/MarketInsights/AverageHistory.cs +++ b/Tools/MarketInsights/AverageHistory.cs @@ -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); } diff --git a/Tools/MarketInsights/Program.cs b/Tools/MarketInsights/Program.cs index a616386f..6caf4433 100644 --- a/Tools/MarketInsights/Program.cs +++ b/Tools/MarketInsights/Program.cs @@ -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); diff --git a/Tools/MarketInsights/Updater.cs b/Tools/MarketInsights/Updater.cs index 87743f66..436a5ac2 100644 --- a/Tools/MarketInsights/Updater.cs +++ b/Tools/MarketInsights/Updater.cs @@ -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() diff --git a/Tools/TestNetRewarder/EventsFormatter.cs b/Tools/TestNetRewarder/EventsFormatter.cs index 3b1650cb..a9c3a0a1 100644 --- a/Tools/TestNetRewarder/EventsFormatter.cs +++ b/Tools/TestNetRewarder/EventsFormatter.cs @@ -123,17 +123,18 @@ namespace TestNetRewarder public void ProcessPeriodReports(PeriodMonitorResult reports) { - if (reports.IsEmpty) return; + //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")}" - }; + //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); + // 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 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 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 lines, PeriodReport report) - { - foreach (var missedProof in report.GetMissedProofs()) - { - DescribeMissedProof(lines, missedProof); - } - } + //private void DescribeMissedProof(List lines, PeriodReport report) + //{ + // foreach (var missedProof in report.GetMissedProofs()) + // { + // DescribeMissedProof(lines, missedProof); + // } + //} - private void DescribeMissedProof(List lines, PeriodProof missedProof) - { - lines.Add($"[{missedProof.FormatHost()}] missed proof for {FormatRequestId(missedProof.Request)} (slotIndex: {missedProof.SlotIndex})"); - } + //private void DescribeMissedProof(List 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) { diff --git a/Tools/TestNetRewarder/Processor.cs b/Tools/TestNetRewarder/Processor.cs index 036f8795..0a459bc6 100644 --- a/Tools/TestNetRewarder/Processor.cs +++ b/Tools/TestNetRewarder/Processor.cs @@ -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); } diff --git a/Tools/TestNetRewarder/Program.cs b/Tools/TestNetRewarder/Program.cs index e3ed24e7..0cac9bd7 100644 --- a/Tools/TestNetRewarder/Program.cs +++ b/Tools/TestNetRewarder/Program.cs @@ -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); diff --git a/Tools/TraceContract/ChainTracer.cs b/Tools/TraceContract/ChainTracer.cs index a4227ab4..40f3195d 100644 --- a/Tools/TraceContract/ChainTracer.cs +++ b/Tools/TraceContract/ChainTracer.cs @@ -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) diff --git a/Tools/TraceContract/Program.cs b/Tools/TraceContract/Program.cs index 50ade56d..5e24af4f 100644 --- a/Tools/TraceContract/Program.cs +++ b/Tools/TraceContract/Program.cs @@ -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,