improves proof period monitoring

This commit is contained in:
Ben 2025-08-13 13:54:33 +02:00
parent 532c0279d5
commit 82fde74c36
No known key found for this signature in database
GPG Key ID: 0F16E812E736C24B
6 changed files with 52 additions and 28 deletions

View File

@ -41,8 +41,8 @@ namespace CodexContractsPlugin.ChainMonitor
private void CreateReportForPeriod(ulong lastBlockInPeriod, ulong periodNumber, IChainStateRequest[] requests)
{
ulong total = 0;
ulong required = 0;
var missed = new List<PeriodProofMissed>();
var required = new List<PeriodProof>();
var missed = new List<PeriodProof>();
foreach (var request in requests)
{
for (ulong slotIndex = 0; slotIndex < request.Request.Ask.Slots; slotIndex++)
@ -52,17 +52,19 @@ namespace CodexContractsPlugin.ChainMonitor
total++;
if (state.Required)
{
required++;
var idx = Convert.ToInt32(slotIndex);
var host = request.Hosts.GetHost(idx);
var proof = new PeriodProof(host, request, idx);
required.Add(proof);
if (state.Missing)
{
var idx = Convert.ToInt32(slotIndex);
var host = request.Hosts.GetHost(idx);
missed.Add(new PeriodProofMissed(host, request, idx));
missed.Add(proof);
}
}
}
}
var report = new PeriodReport(periodNumber, total, required, missed.ToArray());
var report = new PeriodReport(periodNumber, total, required.ToArray(), missed.ToArray());
log.Log($"Period report: {report}");
reports.Add(report);
}
@ -87,45 +89,48 @@ namespace CodexContractsPlugin.ChainMonitor
private void CalcStats()
{
IsEmpty = Reports.All(r => r.TotalProofsRequired == 0);
IsEmpty = Reports.All(r => r.ProofsRequired.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.TotalProofsRequired));
AverageNumProofsRequired = Reports.Average(r => Convert.ToSingle(r.ProofsRequired.Length));
}
}
public class PeriodReport
{
public PeriodReport(ulong periodNumber, ulong totalNumSlots, ulong totalProofsRequired, PeriodProofMissed[] missedProofs)
public PeriodReport(ulong periodNumber, ulong totalNumSlots, PeriodProof[] proofsRequired, PeriodProof[] missedProofs)
{
PeriodNumber = periodNumber;
TotalNumSlots = totalNumSlots;
TotalProofsRequired = totalProofsRequired;
ProofsRequired = proofsRequired;
MissedProofs = missedProofs;
}
public ulong PeriodNumber { get; }
public ulong TotalNumSlots { get; }
public ulong TotalProofsRequired { get; }
public PeriodProofMissed[] MissedProofs { get; }
public PeriodProof[] ProofsRequired { get; }
public PeriodProof[] MissedProofs { get; }
public override string ToString()
{
var missed = "None";
if (MissedProofs.Length > 0)
{
missed = string.Join("+", MissedProofs.Select(p => $"{p.FormatHost()} missed {p.Request.RequestId.ToHex()} slot {p.SlotIndex}"));
}
return $"Period:{PeriodNumber}=[Slots:{TotalNumSlots},ProofsRequired:{TotalProofsRequired},ProofsMissed:{missed}]";
var required = Describe(ProofsRequired);
var missed = Describe(MissedProofs);
return $"Period:{PeriodNumber}=[Slots:{TotalNumSlots},ProofsRequired:{required},ProofsMissed:{missed}]";
}
private string Describe(PeriodProof[] proofs)
{
if (proofs.Length == 0) return "None";
return string.Join("+", proofs.Select(p => $"{p.FormatHost()} - {p.Request.RequestId.ToHex()} slot {p.SlotIndex}"));
}
}
public class PeriodProofMissed
public class PeriodProof
{
public PeriodProofMissed(EthAddress? host, IChainStateRequest request, int slotIndex)
public PeriodProof(EthAddress? host, IChainStateRequest request, int slotIndex)
{
Host = host;
Request = request;

View File

@ -172,7 +172,7 @@ namespace CodexContractsPlugin
var required = IsProofRequired(slotId, blockNumber);
if (!required) return new ProofState(false, false);
var missing = IsProofMissing(slotId, blockNumber, period);
var missing = IsProofMissing(slotId, period, blockNumber);
return new ProofState(required, missing);
}
@ -202,16 +202,19 @@ namespace CodexContractsPlugin
return result.ReturnValue1;
}
private bool IsProofMissing(byte[] slotId, ulong blockNumber, ulong period)
private bool IsProofMissing(byte[] slotId, ulong period, ulong blockNumber)
{
try
{
var funcB = new MarkProofAsMissingFunction
var func = new CanMarkProofAsMissingFunction
{
SlotId = slotId,
Period = period
};
gethNode.Call(Deployment.MarketplaceAddress, funcB, blockNumber);
var result = gethNode.Call<CanMarkProofAsMissingFunction, bool>(Deployment.MarketplaceAddress, func, blockNumber);
var a = 0;
}
catch (AggregateException exc)
{

View File

@ -22,7 +22,7 @@ namespace CodexReleaseTests.MarketTests
Assert.That(purchaseParams.Nodes, Is.LessThan(NumberOfHosts));
}
protected override int NumberOfHosts => 5;
protected override int NumberOfHosts => 6;
protected override int NumberOfClients => 1;
protected override ByteSize HostAvailabilitySize => purchaseParams.SlotSize.Multiply(1.1); // Each host can hold 1 slot.
protected override TimeSpan HostAvailabilityMaxDuration => TimeSpan.FromDays(5.0);
@ -47,6 +47,17 @@ namespace CodexReleaseTests.MarketTests
client.Stop(waitTillStopped: true);
// Hold this situation
Log("Holding initial situation to ensure contract is stable...");
var config = GetContracts().Deployment.Config;
WaitAndCheckNodesStaysAlive(config.PeriodDuration * 5, hosts);
if (contract.GetStatus() == null ||
contract.GetStatus()!.State == StoragePurchaseState.Failed)
{
Assert.Fail("Contract did not survive waiting period.");
}
for (var i = 0; i < numFailures; i++)
{
Log($"Failure step: {i}");

View File

@ -71,7 +71,7 @@ namespace CodexReleaseTests.Utils
if (reports.IsEmpty) return;
var slots = reports.Reports.Sum(r => Convert.ToInt32(r.TotalNumSlots));
var required = reports.Reports.Sum(r => Convert.ToInt32(r.TotalProofsRequired));
var required = reports.Reports.Sum(r => Convert.ToInt32(r.ProofsRequired.Length));
var missed = reports.Reports.Sum(r => r.MissedProofs.Length);
log.Log($"Proof report: Slots={slots} Required={required} Missed={missed}");

View File

@ -127,6 +127,11 @@ namespace CodexTests
WaitAndCheckNodesStaysAlive(duration, nodes.ToArray());
}
public void WaitAndCheckNodesStaysAlive(TimeSpan duration, List<ICodexNode> nodes)
{
WaitAndCheckNodesStaysAlive(duration, nodes.ToArray());
}
public void WaitAndCheckNodesStaysAlive(TimeSpan duration, params ICodexNode[] nodes)
{
Log($"{nameof(WaitAndCheckNodesStaysAlive)} {Time.FormatDuration(duration)}...");

View File

@ -178,7 +178,7 @@ namespace TestNetRewarder
}
}
private void DescribeMissedProof(List<string> lines, PeriodProofMissed missedProof)
private void DescribeMissedProof(List<string> lines, PeriodProof missedProof)
{
lines.Add($"[{missedProof.FormatHost()}] missed proof for {FormatRequestId(missedProof.Request)} (slotIndex: {missedProof.SlotIndex})");
}