Merge branch 'master' into feature/multi-codex-folder-saver

This commit is contained in:
ThatBen 2025-06-06 07:42:46 +02:00
commit bc01e97ff8
No known key found for this signature in database
GPG Key ID: 62C543548433D43E
28 changed files with 329 additions and 83 deletions

View File

@ -22,7 +22,9 @@
.Replace("\\", "-")
.Replace("[", "-")
.Replace("]", "-")
.Replace(",", "-");
.Replace(",", "-")
.Replace("(", "-")
.Replace(")", "-");
if (result.Length > maxLength) result = result.Substring(0, maxLength);
result = result.Trim('-');

View File

@ -40,7 +40,9 @@ namespace KubernetesWorkflow
protected override void ProcessLine(string line)
{
if (line.Contains("Received JSON-RPC response")) return;
// This line is not useful and has no topic so we can't filter it with
// normal log-level controls.
if (line.Contains("Received JSON-RPC response") && !line.Contains("topics=")) return;
if (line.Contains("object field not marked with serialize, skipping")) return;
LogFile.Write(line);

View File

@ -11,7 +11,7 @@ namespace CodexClient
private readonly ILog log;
private readonly IHttpFactory httpFactory;
private readonly IProcessControl processControl;
private ICodexInstance instance;
private readonly ICodexInstance instance;
private readonly Mapper mapper = new Mapper();
public CodexAccess(ILog log, IHttpFactory httpFactory, IProcessControl processControl, ICodexInstance instance)
@ -25,8 +25,6 @@ namespace CodexClient
public void Stop(bool waitTillStopped)
{
processControl.Stop(waitTillStopped);
// Prevents accidental use after stop:
instance = null!;
}
public IDownloadedLog DownloadLog(string additionalName = "")
@ -143,7 +141,7 @@ namespace CodexClient
return mapper.Map(OnCodex(api => api.ListDataAsync()));
}
public StorageAvailability SalesAvailability(StorageAvailability request)
public StorageAvailability SalesAvailability(CreateStorageAvailability request)
{
var body = mapper.Map(request);
var read = OnCodex(api => api.OfferStorageAsync(body));

View File

@ -36,7 +36,7 @@ namespace CodexClient
};
}
public CodexOpenApi.SalesAvailability Map(StorageAvailability availability)
public CodexOpenApi.SalesAvailability Map(CreateStorageAvailability availability)
{
return new CodexOpenApi.SalesAvailability
{
@ -70,15 +70,13 @@ namespace CodexClient
{
return new StorageAvailability
(
availability.Id,
ToByteSize(availability.TotalSize),
ToTimespan(availability.Duration),
new TestToken(ToBigInt(availability.MinPricePerBytePerSecond)),
new TestToken(ToBigInt(availability.TotalCollateral))
)
{
Id = availability.Id,
FreeSpace = ToByteSize(availability.FreeSize),
};
new TestToken(ToBigInt(availability.TotalCollateral)),
ToByteSize(availability.FreeSize)
);
}
public StoragePurchase Map(CodexOpenApi.Purchase purchase)

View File

@ -6,7 +6,7 @@ namespace CodexClient
{
public interface IMarketplaceAccess
{
string MakeStorageAvailable(StorageAvailability availability);
string MakeStorageAvailable(CreateStorageAvailability availability);
StorageAvailability[] GetAvailabilities();
IStoragePurchaseContract RequestStorage(StoragePurchaseRequest purchase);
}
@ -49,7 +49,7 @@ namespace CodexClient
return new StoragePurchaseContract(log, codexAccess, response, purchase, hooks);
}
public string MakeStorageAvailable(StorageAvailability availability)
public string MakeStorageAvailable(CreateStorageAvailability availability)
{
availability.Log(log);
@ -77,7 +77,7 @@ namespace CodexClient
public class MarketplaceUnavailable : IMarketplaceAccess
{
public string MakeStorageAvailable(StorageAvailability availability)
public string MakeStorageAvailable(CreateStorageAvailability availability)
{
Unavailable();
throw new NotImplementedException();

View File

@ -84,9 +84,9 @@ namespace CodexClient
//public PoRParameters Por { get; set; }
}
public class StorageAvailability
public class CreateStorageAvailability
{
public StorageAvailability(ByteSize totalSpace, TimeSpan maxDuration, TestToken minPricePerBytePerSecond, TestToken totalCollateral)
public CreateStorageAvailability(ByteSize totalSpace, TimeSpan maxDuration, TestToken minPricePerBytePerSecond, TestToken totalCollateral)
{
TotalSpace = totalSpace;
MaxDuration = maxDuration;
@ -94,20 +94,49 @@ namespace CodexClient
TotalCollateral = totalCollateral;
}
public string Id { get; set; } = string.Empty;
public ByteSize TotalSpace { get; }
public TimeSpan MaxDuration { get; }
public TestToken MinPricePerBytePerSecond { get; }
public TestToken TotalCollateral { get; }
public ByteSize FreeSpace { get; set; } = ByteSize.Zero;
public TestToken TotalCollateral { get; }
public void Log(ILog log)
{
log.Log($"Storage Availability: (" +
log.Log($"Create storage Availability: (" +
$"totalSize: {TotalSpace}, " +
$"maxDuration: {Time.FormatDuration(MaxDuration)}, " +
$"maxDuration: {Time.FormatDuration(MaxDuration)}, " +
$"minPricePerBytePerSecond: {MinPricePerBytePerSecond}, " +
$"totalCollateral: {TotalCollateral})");
}
}
public class StorageAvailability
{
public StorageAvailability(string id, ByteSize totalSpace, TimeSpan maxDuration, TestToken minPricePerBytePerSecond, TestToken totalCollateral, ByteSize freeSpace)
{
Id = id;
TotalSpace = totalSpace;
MaxDuration = maxDuration;
MinPricePerBytePerSecond = minPricePerBytePerSecond;
TotalCollateral = totalCollateral;
FreeSpace = freeSpace;
}
public string Id { get; }
public ByteSize TotalSpace { get; }
public TimeSpan MaxDuration { get; }
public TestToken MinPricePerBytePerSecond { get; }
public TestToken TotalCollateral { get; }
public ByteSize FreeSpace { get; }
public void Log(ILog log)
{
log.Log($"Storage Availability: (" +
$"id: {Id}, " +
$"totalSize: {TotalSpace}, " +
$"maxDuration: {Time.FormatDuration(MaxDuration)}, " +
$"minPricePerBytePerSecond: {MinPricePerBytePerSecond}, " +
$"totalCollateral: {TotalCollateral}, " +
$"freeSpace: {FreeSpace})");
}
}
}

View File

@ -14,7 +14,13 @@ namespace CodexClient
void WaitForStorageContractSubmitted();
void WaitForStorageContractStarted();
void WaitForStorageContractFinished();
void WaitForContractFailed();
void WaitForContractFailed(IMarketplaceConfigInput config);
}
public interface IMarketplaceConfigInput
{
int MaxNumberOfSlashes { get; }
TimeSpan PeriodDuration { get; }
}
public class StoragePurchaseContract : IStoragePurchaseContract
@ -99,7 +105,7 @@ namespace CodexClient
AssertDuration(SubmittedToFinished, timeout, nameof(SubmittedToFinished));
}
public void WaitForContractFailed()
public void WaitForContractFailed(IMarketplaceConfigInput config)
{
if (!contractStartedUtc.HasValue)
{
@ -107,7 +113,30 @@ namespace CodexClient
}
var currentContractTime = DateTime.UtcNow - contractSubmittedUtc!.Value;
var timeout = (Purchase.Duration - currentContractTime) + gracePeriod;
WaitForStorageContractState(timeout, StoragePurchaseState.Failed);
var minTimeout = TimeNeededToFailEnoughProofsToFreeASlot(config);
if (timeout < minTimeout)
{
throw new ArgumentOutOfRangeException(
$"Test is misconfigured. Assuming a proof is required every period, it will take {Time.FormatDuration(minTimeout)} " +
$"to fail enough proofs for a slot to be freed. But, the storage contract will complete in {Time.FormatDuration(timeout)}. " +
$"Increase the duration."
);
}
WaitForStorageContractState(timeout, StoragePurchaseState.Errored);
}
private TimeSpan TimeNeededToFailEnoughProofsToFreeASlot(IMarketplaceConfigInput config)
{
var numMissedProofsRequiredForFree = config.MaxNumberOfSlashes;
var timePerProof = config.PeriodDuration;
var result = timePerProof * (numMissedProofsRequiredForFree + 1);
// Times 2!
// Because of pointer-downtime it's possible that some periods even though there's a probability of 100%
// will not require any proof. To be safe we take twice the required time.
return result * 2;
}
private void WaitForStorageContractState(TimeSpan timeout, StoragePurchaseState desiredState, int sleep = 1000)
@ -128,7 +157,7 @@ namespace CodexClient
hooks.OnStorageContractUpdated(purchaseStatus);
}
if (lastState == StoragePurchaseState.Errored)
if (desiredState != StoragePurchaseState.Errored && lastState == StoragePurchaseState.Errored)
{
FrameworkAssert.Fail("Contract errored: " + statusJson);
}

View File

@ -47,7 +47,7 @@ namespace CodexContractsPlugin.ChainMonitor
handler = changeHandler;
this.doProofPeriodMonitoring = doProofPeriodMonitoring;
TotalSpan = new TimeRange(startUtc, startUtc);
PeriodMonitor = new PeriodMonitor(contracts);
PeriodMonitor = new PeriodMonitor(log, contracts);
}
public TimeRange TotalSpan { get; private set; }

View File

@ -1,15 +1,18 @@
using Utils;
using Logging;
using Utils;
namespace CodexContractsPlugin.ChainMonitor
{
public class PeriodMonitor
{
private readonly ILog log;
private readonly ICodexContracts contracts;
private readonly List<PeriodReport> reports = new List<PeriodReport>();
private ulong? currentPeriod = null;
public PeriodMonitor(ICodexContracts contracts)
public PeriodMonitor(ILog log, ICodexContracts contracts)
{
this.log = log;
this.contracts = contracts;
}
@ -58,7 +61,9 @@ namespace CodexContractsPlugin.ChainMonitor
}
}
}
reports.Add(new PeriodReport(periodNumber, total, required, missed.ToArray()));
var report = new PeriodReport(periodNumber, total, required, missed.ToArray());
log.Log($"Period report: {report}");
reports.Add(report);
}
}
@ -105,6 +110,16 @@ namespace CodexContractsPlugin.ChainMonitor
public ulong TotalNumSlots { get; }
public ulong TotalProofsRequired { get; }
public PeriodProofMissed[] MissedProofs { get; }
public override string ToString()
{
var missed = "None";
if (MissedProofs.Length > 0)
{
missed = string.Join("+", MissedProofs.Select(p => $"{p.FormatHost()} missed {p.Request.Request.Id} slot {p.SlotIndex}"));
}
return $"Period:{PeriodNumber}=[Slots:{TotalNumSlots},ProofsRequired:{TotalProofsRequired},ProofsMissed:{missed}]";
}
}
public class PeriodProofMissed
@ -119,5 +134,11 @@ namespace CodexContractsPlugin.ChainMonitor
public EthAddress? Host { get; }
public IChainStateRequest Request { get; }
public int SlotIndex { get; }
public string FormatHost()
{
if (Host == null) return "Unknown host";
return Host.Address;
}
}
}

View File

@ -146,7 +146,6 @@ namespace CodexContractsPlugin
public void WaitUntilNextPeriod()
{
log.Log("Waiting until next proof period...");
var now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
var periodSeconds = (int)Deployment.Config.Proofs.Period;
var secondsLeft = now % periodSeconds;

View File

@ -2,6 +2,7 @@
using BlockchainUtils;
using Nethereum.Hex.HexConvertors.Extensions;
using Newtonsoft.Json;
using CodexClient;
using Utils;
namespace CodexContractsPlugin.Marketplace
@ -92,5 +93,11 @@ namespace CodexContractsPlugin.Marketplace
[JsonIgnore]
public BlockTimeEntry Block { get; set; }
}
public partial class MarketplaceConfig : IMarketplaceConfigInput
{
public int MaxNumberOfSlashes => this.Collateral.MaxNumberOfSlashes;
public TimeSpan PeriodDuration => TimeSpan.FromSeconds(this.Proofs.Period);
}
}
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.

File diff suppressed because one or more lines are too long

View File

@ -2,7 +2,7 @@
{
public class CodexDockerImage
{
private const string DefaultDockerImage = "codexstorage/nim-codex:0.2.3-dist-tests";
private const string DefaultDockerImage = "codexstorage/nim-codex:sha-3e17207-dist-tests";
public static string Override { get; set; } = string.Empty;

View File

@ -7,15 +7,22 @@ using Utils;
namespace CodexReleaseTests.DataTests
{
[TestFixture]
[TestFixture(2, 10)]
[TestFixture(5, 20)]
[TestFixture(10, 50)]
public class SwarmTests : AutoBootstrapDistTest
{
private readonly int numberOfNodes;
private readonly int filesizeMb;
public SwarmTests(int numberOfNodes, int filesizeMb)
{
this.numberOfNodes = numberOfNodes;
this.filesizeMb = filesizeMb;
}
[Test]
[Combinatorial]
public void SmallSwarm(
[Values(2)] int numberOfNodes,
[Values(10)] int filesizeMb
)
public void Swarm()
{
var filesize = filesizeMb.MB();
var nodes = StartCodex(numberOfNodes);
@ -28,11 +35,7 @@ namespace CodexReleaseTests.DataTests
}
[Test]
[Combinatorial]
public void StreamlessSmallSwarm(
[Values(2)] int numberOfNodes,
[Values(10)] int filesizeMb
)
public void StreamlessSwarm()
{
var filesize = filesizeMb.MB();
var nodes = StartCodex(numberOfNodes);

View File

@ -0,0 +1,49 @@
using CodexContractsPlugin;
using CodexContractsPlugin.ChainMonitor;
using Logging;
namespace CodexReleaseTests.MarketTests
{
public class ChainMonitor
{
private readonly ChainState chainMonitor;
private readonly TimeSpan interval;
private CancellationTokenSource cts = new CancellationTokenSource();
private Task worker = null!;
public ChainMonitor(ILog log, ICodexContracts contracts, DateTime startUtc, TimeSpan interval)
{
chainMonitor = new ChainState(log, contracts, new DoNothingChainEventHandler(), startUtc, true);
this.interval = interval;
}
public void Start()
{
cts = new CancellationTokenSource();
worker = Task.Run(Worker);
}
public void Stop()
{
cts.Cancel();
worker.Wait();
worker = null!;
cts = null!;
}
public PeriodMonitorResult GetPeriodReports()
{
return chainMonitor.PeriodMonitor.GetAndClearReports();
}
private void Worker()
{
while (!cts.IsCancellationRequested)
{
Thread.Sleep(interval);
chainMonitor.Update();
}
}
}
}

View File

@ -8,11 +8,16 @@ namespace CodexReleaseTests.MarketTests
public class FailTest : MarketplaceAutoBootstrapDistTest
{
protected override int NumberOfHosts => 4;
private readonly int SlotTolerance;
protected override int NumberOfClients => 1;
protected override ByteSize HostAvailabilitySize => 1.GB();
protected override TimeSpan HostAvailabilityMaxDuration => TimeSpan.FromDays(1.0);
[Ignore("Slots are never freed because proofs are never marked as missing. Issue: https://github.com/codex-storage/nim-codex/issues/1153")]
public FailTest()
{
SlotTolerance = NumberOfHosts / 2;
}
[Test]
[Combinatorial]
public void Fail(
@ -35,7 +40,8 @@ namespace CodexReleaseTests.MarketTests
WaitForSlotFreedEvents();
request.WaitForContractFailed();
var config = GetContracts().Deployment.Config;
request.WaitForContractFailed(config);
}
private void WaitForSlotFreedEvents()
@ -49,7 +55,8 @@ namespace CodexReleaseTests.MarketTests
{
var events = GetContracts().GetEvents(GetTestRunTimeRange());
var slotFreed = events.GetSlotFreedEvents();
if (slotFreed.Length == NumberOfHosts)
Log($"SlotFreed events: {slotFreed.Length} - Expected: {SlotTolerance}");
if (slotFreed.Length > SlotTolerance)
{
Log($"{nameof(WaitForSlotFreedEvents)} took {Time.FormatDuration(DateTime.UtcNow - start)}");
return;
@ -67,7 +74,7 @@ namespace CodexReleaseTests.MarketTests
Duration = HostAvailabilityMaxDuration / 2,
Expiry = TimeSpan.FromMinutes(5.0),
MinRequiredNumberOfNodes = (uint)NumberOfHosts,
NodeFailureTolerance = (uint)(NumberOfHosts / 2),
NodeFailureTolerance = (uint)SlotTolerance,
PricePerBytePerSecond = 100.TstWei(),
ProofProbability = 1, // Require a proof every period
CollateralPerByte = 1.TstWei()

View File

@ -6,7 +6,7 @@ using Utils;
namespace CodexReleaseTests.MarketTests
{
[TestFixture(5, 3, 1)]
[TestFixture(10, 20, 10)]
[TestFixture(10, 8, 4)]
public class FinishTest : MarketplaceAutoBootstrapDistTest
{
public FinishTest(int hosts, int slots, int tolerance)
@ -32,6 +32,7 @@ namespace CodexReleaseTests.MarketTests
{
var hosts = StartHosts();
var client = StartClients().Single();
AssertHostAvailabilitiesAreEmpty(hosts);
var request = CreateStorageRequest(client);
@ -46,6 +47,7 @@ namespace CodexReleaseTests.MarketTests
AssertClientHasPaidForContract(pricePerBytePerSecond, client, request, hosts);
AssertHostsWerePaidForContract(pricePerBytePerSecond, request, hosts);
AssertHostsCollateralsAreUnchanged(hosts);
AssertHostAvailabilitiesAreEmpty(hosts);
}
private IStoragePurchaseContract CreateStorageRequest(ICodexNode client)

View File

@ -53,11 +53,15 @@ namespace CodexReleaseTests.Utils
protected abstract ByteSize HostAvailabilitySize { get; }
protected abstract TimeSpan HostAvailabilityMaxDuration { get; }
protected virtual bool MonitorChainState { get; } = true;
protected TimeSpan HostBlockTTL { get; } = TimeSpan.FromMinutes(1.0);
public ICodexNodeGroup StartHosts()
{
var hosts = StartCodex(NumberOfHosts, s => s
.WithName("host")
.WithBlockTTL(HostBlockTTL)
.WithBlockMaintenanceNumber(1000)
.WithBlockMaintenanceInterval(HostBlockTTL / 2)
.EnableMarketplace(GetGeth(), GetContracts(), m => m
.WithInitial(StartingBalanceEth.Eth(), StartingBalanceTST.Tst())
.AsStorageNode()
@ -70,7 +74,7 @@ namespace CodexReleaseTests.Utils
AssertTstBalance(host, StartingBalanceTST.Tst(), nameof(StartHosts));
AssertEthBalance(host, StartingBalanceEth.Eth(), nameof(StartHosts));
host.Marketplace.MakeStorageAvailable(new StorageAvailability(
host.Marketplace.MakeStorageAvailable(new CreateStorageAvailability(
totalSpace: HostAvailabilitySize,
maxDuration: HostAvailabilityMaxDuration,
minPricePerBytePerSecond: 1.TstWei(),
@ -84,6 +88,9 @@ namespace CodexReleaseTests.Utils
{
var host = StartCodex(s => s
.WithName("singlehost")
.WithBlockTTL(HostBlockTTL)
.WithBlockMaintenanceNumber(1000)
.WithBlockMaintenanceInterval(HostBlockTTL / 2)
.EnableMarketplace(GetGeth(), GetContracts(), m => m
.WithInitial(StartingBalanceEth.Eth(), StartingBalanceTST.Tst())
.AsStorageNode()
@ -94,7 +101,7 @@ namespace CodexReleaseTests.Utils
AssertTstBalance(host, StartingBalanceTST.Tst(), nameof(StartOneHost));
AssertEthBalance(host, StartingBalanceEth.Eth(), nameof(StartOneHost));
host.Marketplace.MakeStorageAvailable(new StorageAvailability(
host.Marketplace.MakeStorageAvailable(new CreateStorageAvailability(
totalSpace: HostAvailabilitySize,
maxDuration: HostAvailabilityMaxDuration,
minPricePerBytePerSecond: 1.TstWei(),
@ -103,6 +110,30 @@ namespace CodexReleaseTests.Utils
return host;
}
public void AssertHostAvailabilitiesAreEmpty(IEnumerable<ICodexNode> hosts)
{
var retry = GetAvailabilitySpaceAssertRetry();
retry.Run(() =>
{
foreach (var host in hosts)
{
AssertHostAvailabilitiesAreEmpty(host);
}
});
}
private void AssertHostAvailabilitiesAreEmpty(ICodexNode host)
{
var availabilities = host.Marketplace.GetAvailabilities();
foreach (var a in availabilities)
{
if (a.FreeSpace.SizeInBytes != a.TotalSpace.SizeInBytes)
{
throw new Exception(nameof(AssertHostAvailabilitiesAreEmpty) + $" free: {a.FreeSpace} total: {a.TotalSpace}");
}
}
}
public void AssertTstBalance(ICodexNode node, TestToken expectedBalance, string message)
{
AssertTstBalance(node.EthAddress, expectedBalance, message);
@ -160,6 +191,15 @@ namespace CodexReleaseTests.Utils
failFast: false);
}
private Retry GetAvailabilitySpaceAssertRetry()
{
return new Retry("AssertAvailabilitySpace",
maxTimeout: HostBlockTTL * 3,
sleepAfterFail: TimeSpan.FromSeconds(10.0),
onFail: f => { },
failFast: false);
}
private TestToken GetTstBalance(ICodexNode node)
{
return GetContracts().GetTestTokenBalance(node);

View File

@ -10,7 +10,6 @@ namespace DistTestCore.Helpers
{
try
{
Time.WaitUntil(() => {
var c = constraint.Resolve();
return c.ApplyTo(actual()).IsSuccess;

View File

@ -28,10 +28,11 @@ namespace DistTestCore
public static string GetRawFixtureName()
{
var test = TestContext.CurrentContext.Test;
if (test.ClassName!.Contains("AdhocContext")) return "none";
var className = test.ClassName!.Substring(test.ClassName.LastIndexOf('.') + 1);
className += FormatArguments(test);
return className.Replace('.', '-');
var fullName = test.FullName;
if (fullName.Contains("AdhocContext")) return "none";
var name = fullName.Substring(0, fullName.LastIndexOf('.'));
name += FormatArguments(test);
return name.Replace('.', '-').Replace(',', '-');
}
public static string GetCategoryName()

View File

@ -50,7 +50,7 @@ namespace ExperimentalTests.BasicTests
{
AssertBalance(contracts, host, Is.EqualTo(hostInitialBalance), "Host initial balance");
var availability = new StorageAvailability(
var availability = new CreateStorageAvailability(
totalSpace: 10.GB(),
maxDuration: TimeSpan.FromMinutes(30),
minPricePerBytePerSecond: 1.TstWei(),

View File

@ -97,6 +97,7 @@ namespace CodexTests
public void AssertBalance(ICodexContracts contracts, ICodexNode codexNode, Constraint constraint, string msg)
{
Assert.Fail("Depricated, use MarketplaceAutobootstrapDistTest assertBalances instead.");
AssertHelpers.RetryAssert(constraint, () => contracts.GetTestTokenBalance(codexNode), nameof(AssertBalance) + msg);
}

View File

@ -0,0 +1,46 @@
using GethPlugin;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Utils;
namespace FrameworkTests.Utils
{
[TestFixture]
public class EthAddressEqualityTests
{
[Test]
[Combinatorial]
public void Equal(
[Values(1, 2, 3, 4, 5)] int runs
)
{
var account = EthAccountGenerator.GenerateNew();
var str = account.EthAddress.Address;
var addr = new EthAddress(str);
Assert.That(addr, Is.EqualTo(account.EthAddress));
Assert.That(addr == account.EthAddress);
Assert.That(!(addr != account.EthAddress));
}
[Test]
[Combinatorial]
public void NotEqual(
[Values(1, 2, 3, 4, 5)] int runs
)
{
var account1 = EthAccountGenerator.GenerateNew();
var account2 = EthAccountGenerator.GenerateNew();
Assert.That(account1.EthAddress, Is.Not.EqualTo(account2.EthAddress));
Assert.That(account1.EthAddress != account2.EthAddress);
Assert.That(!(account1.EthAddress == account2.EthAddress));
}
}
}

View File

@ -17,6 +17,13 @@
public string EncodedCid { get; set; } = string.Empty;
public string PurchaseId { get; set; } = string.Empty;
public DateTime PurchaseFinishedUtc { get; set; } = DateTime.MinValue;
public void ClearPurchase()
{
EncodedCid = string.Empty;
PurchaseId = string.Empty;
PurchaseFinishedUtc = DateTime.MinValue;
}
}
[Serializable]

View File

@ -69,7 +69,7 @@ namespace CodexNetDeployer
if (config.ShouldMakeStorageAvailable)
{
var availability = new StorageAvailability(
var availability = new CreateStorageAvailability(
totalSpace: config.StorageSell!.Value.MB(),
maxDuration: TimeSpan.FromSeconds(config.MaxDuration),
minPricePerBytePerSecond: config.MinPricePerBytePerSecond.TstWei(),

View File

@ -165,13 +165,7 @@ namespace TestNetRewarder
private void DescribeMissedProof(List<string> 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;
lines.Add($"[{missedProof.FormatHost()}] missed proof for {FormatRequestId(missedProof.Request)} (slotIndex: {missedProof.SlotIndex})");
}
private void AddRequestBlock(RequestEvent requestEvent, string eventName, params string[] content)

View File

@ -39,16 +39,16 @@
public Dictionary<string, string> LogReplacements = new()
{
{ "0xa1f988fBa23EFd5fA36F4c1a2D1E3c83e25bee4e", "codex 01" },
{ "0xa26a91310F9f2987AA7e0b1ca70e5C474c88ed34", "codex 02" },
{ "0x0CDC9d2D375300C46E13a679cD9eA5299A4FAc74", "codex 03" },
{ "0x7AF1a49A4a52e4bCe3789Ce3d43ff8AD8c8F2118", "codex 04" },
{ "0xfbbEB320c6c775f6565c7bcC732b2813Dd6E0cd3", "codex 05" },
{ "0x4A904CA0998B643eb42d4ae190a5821A4ac51E68", "codex 06" },
{ "0x2b8Ea47d0966B26DEec485c0fCcF0D1A8b52A0e8", "codex 07" },
{ "0x78F90A61d9a2aA93B61A7503Cc2177fFEF379021", "codex 08" },
{ "0xE7EEb996B3c817cEd03d10cd64A1325DA33D92e7", "codex 09" },
{ "0xD25C7609e97F40b66E74c0FcEbeA06D09423CC7e", "codex 10" }
{ "0x3620ec38d88e9f0cf7feceebf97864f27676aa3e", "codex-01" },
{ "0xd80dc50af2a826f2cddc13840d05aed4ee6536c3", "codex-02" },
{ "0x2d1cd0fa0c7e0d29e7b2482b9ff87d5e7b76b905", "codex-03" },
{ "0xd47063bb6e56c9a6edb7612d33ad7d49eeb55ee0", "codex-04" },
{ "0x069da63e29b12a3828984379fcbd7dd3ee3774aa", "codex-05" },
{ "0x43fcceb2a9ce4761ccaa4c9f8d390c7581c190aa", "codex-06" },
{ "0x1a30cef06dbbf8ec25062e4e8d22e8df292f5054", "codex-07" },
{ "0xe169b5dcbae9a7392072323aaf5a677a33d67ecd", "codex-08" },
{ "0x21f7428619ef9f53addc5dab6723c822a8a96b42", "codex-09" },
{ "0xf9bd20512de2d5ca0dcfd8d3cd08a2821917797a", "codex-10" }
};
public string GetElasticSearchUsername()

View File

@ -28,21 +28,22 @@ namespace TraceContract
public Output(ILog log, Input input, Config config)
{
this.input = input;
this.config = config;
folder = config.GetOuputFolder();
Directory.CreateDirectory(folder);
var filename = Path.Combine(folder, $"contract_{input.PurchaseId}");
var fileLog = new FileLog(filename);
log.Log($"Logging to '{filename}'");
this.log = new LogSplitter(fileLog, log);
foreach (var pair in config.LogReplacements)
{
fileLog.AddStringReplace(pair.Key, pair.Value);
fileLog.AddStringReplace(pair.Key.ToLowerInvariant(), pair.Value);
this.log.AddStringReplace(pair.Key, pair.Value);
this.log.AddStringReplace(pair.Key.ToLowerInvariant(), pair.Value);
}
log.Log($"Logging to '{filename}'");
this.log = new LogSplitter(fileLog, log);
this.input = input;
this.config = config;
}
public void LogRequestCreated(RequestEvent requestEvent)