183 lines
6.7 KiB
C#
Raw Normal View History

2025-08-15 12:02:33 +02:00
using CodexContractsPlugin.Marketplace;
using GethPlugin;
using Logging;
using Nethereum.Contracts;
using Nethereum.Hex.HexConvertors.Extensions;
2025-08-13 15:23:31 +02:00
using Nethereum.Model;
2025-08-15 12:02:33 +02:00
using Nethereum.RPC.Eth.DTOs;
using Newtonsoft.Json;
using System.Reflection;
namespace CodexContractsPlugin.ChainMonitor
{
public class PeriodMonitor
{
2025-06-04 12:46:25 +02:00
private readonly ILog log;
private readonly ICodexContracts contracts;
2025-08-15 12:02:33 +02:00
private readonly IGethNode geth;
private readonly List<PeriodReport> reports = new List<PeriodReport>();
2025-08-15 12:02:33 +02:00
private CurrentPeriod? currentPeriod = null;
2025-08-15 12:02:33 +02:00
public PeriodMonitor(ILog log, ICodexContracts contracts, IGethNode geth)
{
2025-06-04 12:46:25 +02:00
this.log = log;
this.contracts = contracts;
2025-08-15 12:02:33 +02:00
this.geth = geth;
}
2025-08-13 15:23:31 +02:00
public void Update(DateTime eventUtc, IChainStateRequest[] requests)
{
2025-08-15 12:02:33 +02:00
var periodNumber = contracts.GetPeriodNumber(eventUtc);
if (currentPeriod == null)
{
2025-08-15 12:02:33 +02:00
currentPeriod = CreateCurrentPeriod(periodNumber, requests);
return;
}
2025-08-15 12:02:33 +02:00
if (periodNumber == currentPeriod.PeriodNumber) return;
2025-08-15 12:02:33 +02:00
CreateReportForPeriod(currentPeriod, requests);
currentPeriod = CreateCurrentPeriod(periodNumber, requests);
}
public PeriodMonitorResult GetAndClearReports()
{
var result = reports.ToArray();
reports.Clear();
return new PeriodMonitorResult(result);
}
2025-08-15 12:02:33 +02:00
private CurrentPeriod CreateCurrentPeriod(ulong periodNumber, IChainStateRequest[] requests)
{
2025-08-15 12:02:33 +02:00
var result = new CurrentPeriod(periodNumber);
ForEachActiveSlot(requests, (request, slotIndex) =>
{
2025-08-15 12:02:33 +02:00
if (contracts.IsProofRequired(request.RequestId, slotIndex))
{
2025-08-13 15:23:31 +02:00
var idx = Convert.ToInt32(slotIndex);
var host = request.Hosts.GetHost(idx);
2025-08-15 12:02:33 +02:00
if (host != null)
{
result.RequiredProofs.Add(new PeriodRequiredProof(host, request, idx));
}
}
2025-08-15 12:02:33 +02:00
});
2025-08-15 12:02:33 +02:00
return result;
}
2025-08-15 12:02:33 +02:00
private void CreateReportForPeriod(CurrentPeriod currentPeriod, IChainStateRequest[] requests)
{
2025-08-15 12:02:33 +02:00
// Fetch function calls during period. Format report.
var timeRange = contracts.GetPeriodTimeRange(currentPeriod.PeriodNumber);
var blockRange = geth.ConvertTimeRangeToBlockRange(timeRange);
2025-08-15 12:02:33 +02:00
var callReports = new List<FunctionCallReport>();
geth.IterateTransactions(blockRange, (t, blkI, blkUtc) =>
{
2025-08-21 09:54:46 +02:00
var reporter = new CallReporter(callReports, t, blkUtc, blkI);
reporter.Run();
2025-08-15 12:02:33 +02:00
});
var report = new PeriodReport(
2025-08-21 09:54:46 +02:00
new ProofPeriod(currentPeriod.PeriodNumber, timeRange, blockRange),
2025-08-15 12:02:33 +02:00
currentPeriod.RequiredProofs.ToArray(),
callReports.ToArray());
2025-03-11 15:00:27 +01:00
2025-08-15 12:02:33 +02:00
report.Log(log);
reports.Add(report);
2025-08-13 13:54:33 +02:00
}
2025-08-15 12:02:33 +02:00
private void ForEachActiveSlot(IChainStateRequest[] requests, Action<IChainStateRequest, ulong> action)
2025-08-13 15:23:31 +02:00
{
2025-08-15 12:02:33 +02:00
foreach (var request in requests)
2025-08-13 15:23:31 +02:00
{
2025-08-15 12:02:33 +02:00
for (ulong slotIndex = 0; slotIndex < request.Request.Ask.Slots; slotIndex++)
{
action(request, slotIndex);
}
2025-08-13 15:23:31 +02:00
}
2025-03-11 15:00:27 +01:00
}
}
2025-08-21 09:54:46 +02:00
public class CallReporter
{
private readonly List<FunctionCallReport> reports;
private readonly Transaction t;
private readonly DateTime blockUtc;
private readonly ulong blockNumber;
public CallReporter(List<FunctionCallReport> reports, Transaction t, DateTime blockUtc, ulong blockNumber)
{
this.reports = reports;
this.t = t;
this.blockUtc = blockUtc;
this.blockNumber = blockNumber;
}
public void Run()
{
CreateFunctionCallReport<CanMarkProofAsMissingFunction>();
CreateFunctionCallReport<CanReserveSlotFunction>();
CreateFunctionCallReport<ConfigurationFunction>();
CreateFunctionCallReport<CurrentCollateralFunction>();
CreateFunctionCallReport<FillSlotFunction>();
CreateFunctionCallReport<FreeSlot1Function>();
CreateFunctionCallReport<FreeSlotFunction>();
CreateFunctionCallReport<GetActiveSlotFunction>();
CreateFunctionCallReport<GetChallengeFunction>();
CreateFunctionCallReport<GetHostFunction>();
CreateFunctionCallReport<GetPointerFunction>();
CreateFunctionCallReport<GetRequestFunction>();
CreateFunctionCallReport<IsProofRequiredFunction>();
CreateFunctionCallReport<MarkProofAsMissingFunction>();
CreateFunctionCallReport<MissingProofsFunction>();
CreateFunctionCallReport<MyRequestsFunction>();
CreateFunctionCallReport<MySlotsFunction>();
CreateFunctionCallReport<RequestEndFunction>();
CreateFunctionCallReport<RequestExpiryFunction>();
CreateFunctionCallReport<RequestStateFunction>();
CreateFunctionCallReport<RequestStorageFunction>();
CreateFunctionCallReport<ReserveSlotFunction>();
CreateFunctionCallReport<SlotProbabilityFunction>();
CreateFunctionCallReport<SlotStateFunction>();
CreateFunctionCallReport<SubmitProofFunction>();
CreateFunctionCallReport<TokenFunction>();
CreateFunctionCallReport<WillProofBeRequiredFunction>();
CreateFunctionCallReport<WithdrawFundsFunction>();
CreateFunctionCallReport<WithdrawFunds1Function>();
}
private void CreateFunctionCallReport<TFunc>() where TFunc : FunctionMessage, new()
{
if (t.IsTransactionForFunctionMessage<TFunc>())
{
var func = t.DecodeTransactionToFunctionMessage<TFunc>();
reports.Add(new FunctionCallReport(blockUtc, blockNumber, typeof(TFunc).Name, JsonConvert.SerializeObject(func)));
}
}
}
2025-08-15 12:02:33 +02:00
public class PeriodMonitorResult
{
2025-08-15 12:02:33 +02:00
public PeriodMonitorResult(PeriodReport[] reports)
{
2025-08-15 12:02:33 +02:00
Reports = reports;
}
2025-08-15 12:02:33 +02:00
public PeriodReport[] Reports { get; }
}
2025-03-11 15:00:27 +01:00
2025-08-15 12:02:33 +02:00
public class CurrentPeriod
{
public CurrentPeriod(ulong periodNumber)
2025-03-11 15:00:27 +01:00
{
2025-08-15 12:02:33 +02:00
PeriodNumber = periodNumber;
2025-03-11 15:00:27 +01:00
}
2025-08-13 15:23:31 +02:00
2025-08-15 12:02:33 +02:00
public ulong PeriodNumber { get; }
public List<PeriodRequiredProof> RequiredProofs { get; } = new List<PeriodRequiredProof>();
}
}