132 lines
4.4 KiB
C#
Raw Normal View History

2025-05-20 14:16:33 +02:00
using CodexContractsPlugin;
using CodexContractsPlugin.ChainMonitor;
using CodexContractsPlugin.Marketplace;
2025-08-15 12:02:33 +02:00
using GethPlugin;
2025-05-20 14:16:33 +02:00
using Logging;
using Nethereum.Hex.HexConvertors.Extensions;
using Nethereum.Model;
2025-05-20 14:16:33 +02:00
using Utils;
namespace TraceContract
{
public class ChainTracer
{
private readonly ILog log;
2025-08-15 12:02:33 +02:00
private readonly IGethNode geth;
2025-05-20 14:16:33 +02:00
private readonly ICodexContracts contracts;
private readonly Input input;
private readonly Output output;
2025-08-15 12:02:33 +02:00
public ChainTracer(ILog log, IGethNode geth, ICodexContracts contracts, Input input, Output output)
2025-05-20 14:16:33 +02:00
{
this.log = log;
2025-08-15 12:02:33 +02:00
this.geth = geth;
2025-05-20 14:16:33 +02:00
this.contracts = contracts;
this.input = input;
this.output = output;
}
public TimeRange TraceChainTimeline()
{
log.Log("Querying blockchain...");
var request = GetRequest();
if (request == null) throw new Exception("Failed to find the purchase in the last week of transactions.");
var creationEvent = FindRequestCreationEvent();
2025-05-20 14:16:33 +02:00
log.Log($"Request started at {creationEvent.Block.Utc}");
var contractEnd = RunToContractEnd(creationEvent);
var requestTimeline = new TimeRange(creationEvent.Block.Utc.AddMinutes(-1.0), contractEnd.AddMinutes(1.0));
2025-05-20 14:16:33 +02:00
log.Log($"Request timeline: {requestTimeline.From} -> {requestTimeline.To}");
// For this timeline, we log all the calls to reserve-slot.
var events = contracts.GetEvents(requestTimeline);
2025-05-22 13:55:03 +02:00
events.GetReserveSlotCalls(call =>
{
if (IsThisRequest(call.RequestId))
{
output.LogReserveSlotCall(call);
log.Log("Found reserve-slot call for slotIndex " + call.SlotIndex);
}
});
2025-05-20 14:16:33 +02:00
log.Log("Writing blockchain output...");
output.WriteContractEvents();
return requestTimeline;
}
private DateTime RunToContractEnd(StorageRequestedEventDTO request)
2025-05-20 14:16:33 +02:00
{
var utc = request.Block.Utc.AddMinutes(-1.0);
var tracker = new ChainRequestTracker(output, input.PurchaseId);
var ignoreLog = new NullLog();
2025-08-15 12:02:33 +02:00
var chainState = new ChainState(ignoreLog, geth, contracts, tracker, utc, false);
2025-05-20 14:16:33 +02:00
var atNow = false;
while (!tracker.IsFinished && !atNow)
2025-05-20 14:16:33 +02:00
{
utc += TimeSpan.FromHours(1.0);
if (utc > DateTime.UtcNow)
{
log.Log("Caught up to present moment without finding contract end.");
utc = DateTime.UtcNow;
atNow = true;
2025-05-20 14:16:33 +02:00
}
log.Log($"Querying up to {utc}");
chainState.Update(utc);
}
if (atNow) return utc;
2025-05-20 14:16:33 +02:00
return tracker.FinishUtc;
}
private bool IsThisRequest(byte[] requestId)
{
return requestId.ToHex().ToLowerInvariant() == input.PurchaseId.ToLowerInvariant();
}
2025-05-20 14:16:33 +02:00
private Request? GetRequest()
{
return contracts.GetRequest(input.RequestId);
2025-05-20 14:16:33 +02:00
}
public StorageRequestedEventDTO FindRequestCreationEvent()
2025-05-20 14:16:33 +02:00
{
var range = new TimeRange(DateTime.UtcNow - TimeSpan.FromHours(3.0), DateTime.UtcNow);
var limit = DateTime.UtcNow - TimeSpan.FromDays(30);
2025-05-20 14:16:33 +02:00
while (range.From > limit)
2025-05-20 14:16:33 +02:00
{
var events = contracts.GetEvents(range);
foreach (var r in events.GetStorageRequestedEvents())
2025-05-20 14:16:33 +02:00
{
if (r.RequestId.ToHex() == input.RequestId.ToHex()) return r;
2025-05-20 14:16:33 +02:00
}
range = new TimeRange(range.From - TimeSpan.FromHours(3.0), range.From);
}
2025-05-20 14:16:33 +02:00
throw new Exception("Unable to find storage request creation event on-chain after (limit) " + Time.FormatTimestamp(limit));
2025-05-20 14:16:33 +02:00
}
private static TimeRange LastHour()
{
return new TimeRange(DateTime.UtcNow.AddHours(-1.0), DateTime.UtcNow);
}
private static TimeRange LastDay()
{
return new TimeRange(DateTime.UtcNow.AddDays(-1.0), DateTime.UtcNow);
}
private static TimeRange LastWeek()
{
return new TimeRange(DateTime.UtcNow.AddDays(-7.0), DateTime.UtcNow);
}
}
}