diff --git a/ProjectPlugins/CodexDiscordBotPlugin/DiscordBotStartupConfig.cs b/ProjectPlugins/CodexDiscordBotPlugin/DiscordBotStartupConfig.cs index bbef0b1..b990e60 100644 --- a/ProjectPlugins/CodexDiscordBotPlugin/DiscordBotStartupConfig.cs +++ b/ProjectPlugins/CodexDiscordBotPlugin/DiscordBotStartupConfig.cs @@ -27,7 +27,7 @@ public class RewarderBotStartupConfig { - public RewarderBotStartupConfig(string discordBotHost, int discordBotPort, string intervalMinutes, DateTime historyStartUtc, DiscordBotGethInfo gethInfo, string? dataPath) + public RewarderBotStartupConfig(string discordBotHost, int discordBotPort, int intervalMinutes, DateTime historyStartUtc, DiscordBotGethInfo gethInfo, string? dataPath) { DiscordBotHost = discordBotHost; DiscordBotPort = discordBotPort; @@ -39,7 +39,7 @@ public string DiscordBotHost { get; } public int DiscordBotPort { get; } - public string IntervalMinutes { get; } + public int IntervalMinutes { get; } public DateTime HistoryStartUtc { get; } public DiscordBotGethInfo GethInfo { get; } public string? DataPath { get; set; } diff --git a/ProjectPlugins/CodexDiscordBotPlugin/RewarderBotContainerRecipe.cs b/ProjectPlugins/CodexDiscordBotPlugin/RewarderBotContainerRecipe.cs index 816c910..ae31e69 100644 --- a/ProjectPlugins/CodexDiscordBotPlugin/RewarderBotContainerRecipe.cs +++ b/ProjectPlugins/CodexDiscordBotPlugin/RewarderBotContainerRecipe.cs @@ -17,7 +17,7 @@ namespace CodexDiscordBotPlugin AddEnvVar("DISCORDBOTHOST", config.DiscordBotHost); AddEnvVar("DISCORDBOTPORT", config.DiscordBotPort.ToString()); - AddEnvVar("INTERVALMINUTES", config.IntervalMinutes); + AddEnvVar("INTERVALMINUTES", config.IntervalMinutes.ToString()); var offset = new DateTimeOffset(config.HistoryStartUtc); AddEnvVar("CHECKHISTORY", offset.ToUnixTimeSeconds().ToString()); diff --git a/ProjectPlugins/CodexPlugin/CodexNode.cs b/ProjectPlugins/CodexPlugin/CodexNode.cs index 36fb1dc..33c249a 100644 --- a/ProjectPlugins/CodexPlugin/CodexNode.cs +++ b/ProjectPlugins/CodexPlugin/CodexNode.cs @@ -23,6 +23,7 @@ namespace CodexPlugin CrashWatcher CrashWatcher { get; } PodInfo GetPodInfo(); ITransferSpeeds TransferSpeeds { get; } + EthAccount EthAccount { get; } void Stop(bool waitTillStopped); } @@ -30,13 +31,13 @@ namespace CodexPlugin { private const string UploadFailedMessage = "Unable to store block"; private readonly IPluginTools tools; - private readonly EthAddress? ethAddress; + private readonly EthAccount? ethAccount; private readonly TransferSpeeds transferSpeeds; - public CodexNode(IPluginTools tools, CodexAccess codexAccess, CodexNodeGroup group, IMarketplaceAccess marketplaceAccess, EthAddress? ethAddress) + public CodexNode(IPluginTools tools, CodexAccess codexAccess, CodexNodeGroup group, IMarketplaceAccess marketplaceAccess, EthAccount? ethAccount) { this.tools = tools; - this.ethAddress = ethAddress; + this.ethAccount = ethAccount; CodexAccess = codexAccess; Group = group; Marketplace = marketplaceAccess; @@ -66,8 +67,17 @@ namespace CodexPlugin { get { - if (ethAddress == null) throw new Exception("Marketplace is not enabled for this Codex node. Please start it with the option '.EnableMarketplace(...)' to enable it."); - return ethAddress; + EnsureMarketplace(); + return ethAccount!.EthAddress; + } + } + + public EthAccount EthAccount + { + get + { + EnsureMarketplace(); + return ethAccount!; } } @@ -197,6 +207,11 @@ namespace CodexPlugin } } + private void EnsureMarketplace() + { + if (ethAccount == null) throw new Exception("Marketplace is not enabled for this Codex node. Please start it with the option '.EnableMarketplace(...)' to enable it."); + } + private void Log(string msg) { tools.GetLog().Log($"{GetName()}: {msg}"); diff --git a/ProjectPlugins/CodexPlugin/CodexNodeFactory.cs b/ProjectPlugins/CodexPlugin/CodexNodeFactory.cs index 18483de..425d489 100644 --- a/ProjectPlugins/CodexPlugin/CodexNodeFactory.cs +++ b/ProjectPlugins/CodexPlugin/CodexNodeFactory.cs @@ -22,22 +22,22 @@ namespace CodexPlugin public CodexNode CreateOnlineCodexNode(CodexAccess access, CodexNodeGroup group) { - var ethAddress = GetEthAddress(access); - var marketplaceAccess = GetMarketplaceAccess(access, ethAddress); - return new CodexNode(tools, access, group, marketplaceAccess, ethAddress); + var ethAccount = GetEthAccount(access); + var marketplaceAccess = GetMarketplaceAccess(access, ethAccount); + return new CodexNode(tools, access, group, marketplaceAccess, ethAccount); } - private IMarketplaceAccess GetMarketplaceAccess(CodexAccess codexAccess, EthAddress? ethAddress) + private IMarketplaceAccess GetMarketplaceAccess(CodexAccess codexAccess, EthAccount? ethAccount) { - if (ethAddress == null) return new MarketplaceUnavailable(); + if (ethAccount == null) return new MarketplaceUnavailable(); return new MarketplaceAccess(tools.GetLog(), codexAccess); } - private EthAddress? GetEthAddress(CodexAccess access) + private EthAccount? GetEthAccount(CodexAccess access) { var ethAccount = access.Container.Containers.Single().Recipe.Additionals.Get(); if (ethAccount == null) return null; - return ethAccount.EthAddress; + return ethAccount; } public CrashWatcher CreateCrashWatcher(RunningContainer c) diff --git a/Tests/CodexTests/BasicTests/MarketplaceTests.cs b/Tests/CodexTests/BasicTests/MarketplaceTests.cs index 7cff4aa..2ecc325 100644 --- a/Tests/CodexTests/BasicTests/MarketplaceTests.cs +++ b/Tests/CodexTests/BasicTests/MarketplaceTests.cs @@ -65,8 +65,8 @@ namespace CodexTests.BasicTests MinRequiredNumberOfNodes = 5, NodeFailureTolerance = 2, ProofProbability = 5, - Duration = TimeSpan.FromMinutes(5), - Expiry = TimeSpan.FromMinutes(4) + Duration = TimeSpan.FromMinutes(6), + Expiry = TimeSpan.FromMinutes(5) }; var purchaseContract = client.Marketplace.RequestStorage(purchase); diff --git a/Tests/CodexTests/UtilityTests/DiscordBotTests.cs b/Tests/CodexTests/UtilityTests/DiscordBotTests.cs index cfb1dfa..ab63112 100644 --- a/Tests/CodexTests/UtilityTests/DiscordBotTests.cs +++ b/Tests/CodexTests/UtilityTests/DiscordBotTests.cs @@ -19,7 +19,7 @@ namespace CodexTests.UtilityTests private readonly TestToken hostInitialBalance = 3000000.TstWei(); private readonly TestToken clientInitialBalance = 1000000000.TstWei(); private readonly EthAccount clientAccount = EthAccount.GenerateNew(); - private readonly EthAccount hostAccount = EthAccount.GenerateNew(); + private readonly List hostAccounts = new List(); [Test] public void BotRewardTest() @@ -44,28 +44,27 @@ namespace CodexTests.UtilityTests var apiCalls = new RewardApiCalls(Ci, botContainer); apiCalls.Start(OnCommand); - Thread.Sleep(TimeSpan.FromMinutes(10)); + purchaseContract.WaitForStorageContractFinished(); apiCalls.Stop(); monitor.Stop(); + + Log("Done!"); } private void OnCommand(GiveRewardsCommand call) { - var line = ""; - if (call.Averages.Any()) line += $"{call.Averages.Length} average. "; - if (call.EventsOverview.Any()) line += $"{call.EventsOverview.Length} events. "; + if (call.Averages.Any()) Log($"{call.Averages.Length} average."); + if (call.EventsOverview.Any()) Log($"{call.EventsOverview.Length} events."); foreach (var r in call.Rewards) { var reward = repo.Rewards.Single(a => a.RoleId == r.RewardId); - var isClient = r.UserAddresses.Any(a => a == clientAccount.EthAddress.Address); - var isHost = r.UserAddresses.Any(a => a == hostAccount.EthAddress.Address); - if (isHost && isClient) throw new Exception("what?"); - var name = isClient ? "Client" : "Host"; - - line += name + " = " + reward.Message; + foreach (var address in r.UserAddresses) + { + var user = IdentifyAccount(address); + Log(user + ": " + reward.Message); + } } - Log(line); } private StoragePurchaseContract ClientPurchasesStorage(ICodexNode client) @@ -88,11 +87,14 @@ namespace CodexTests.UtilityTests private ICodexNode StartClient(IGethNode geth, ICodexContracts contracts) { - return StartCodex(s => s + var node = StartCodex(s => s .WithName("Client") .EnableMarketplace(geth, contracts, m => m .WithAccount(clientAccount) .WithInitial(10.Eth(), clientInitialBalance))); + + Log($"Client {node.EthAccount.EthAddress}"); + return node; } private void StartRewarderBot(DiscordBotGethInfo gethInfo, RunningContainer botContainer) @@ -100,7 +102,7 @@ namespace CodexTests.UtilityTests Ci.DeployRewarderBot(new RewarderBotStartupConfig( discordBotHost: botContainer.GetInternalAddress(DiscordBotContainerRecipe.RewardsPort).Host, discordBotPort: botContainer.GetInternalAddress(DiscordBotContainerRecipe.RewardsPort).Port, - intervalMinutes: "10", + intervalMinutes: 1, historyStartUtc: DateTime.UtcNow, gethInfo: gethInfo, dataPath: null @@ -142,23 +144,27 @@ namespace CodexTests.UtilityTests { ContractClock = CodexLogLevel.Trace, }) - .WithStorageQuota(GetFileSizePlus(50)) + .WithStorageQuota(Mult(GetMinFileSizePlus(50), GetNumberOfLiveHosts())) .EnableMarketplace(geth, contracts, m => m - .WithAccount(hostAccount) .WithInitial(10.Eth(), hostInitialBalance) .AsStorageNode() .AsValidator())); var availability = new StorageAvailability( - totalSpace: GetFileSizePlus(5), + totalSpace: Mult(GetMinFileSize(), GetNumberOfLiveHosts()), maxDuration: TimeSpan.FromMinutes(30), minPriceForTotalSpace: 1.TstWei(), maxCollateral: hostInitialBalance ); + var i = 0; foreach (var host in hosts) { + hostAccounts.Add(host.EthAccount); host.Marketplace.MakeStorageAvailable(availability); + + Log($"Host{i} {host.EthAccount.EthAddress}"); + i++; } } @@ -167,7 +173,12 @@ namespace CodexTests.UtilityTests return Convert.ToInt32(GetNumberOfRequiredHosts()) + 3; } - private ByteSize GetFileSizePlus(int plusMb) + private ByteSize Mult(ByteSize size, int mult) + { + return new ByteSize(size.SizeInBytes * mult); + } + + private ByteSize GetMinFileSizePlus(int plusMb) { return new ByteSize(GetMinFileSize().SizeInBytes + plusMb.MB().SizeInBytes); } @@ -184,7 +195,7 @@ namespace CodexTests.UtilityTests if (h > minNumHosts) minNumHosts = h; } - var minFileSize = (minSlotSize * minNumHosts) + 1024; + var minFileSize = ((minSlotSize + 1024) * minNumHosts); return new ByteSize(Convert.ToInt64(minFileSize)); } @@ -193,6 +204,20 @@ namespace CodexTests.UtilityTests return Convert.ToUInt32(repo.Rewards.Max(r => r.CheckConfig.MinNumberOfHosts)); } + private string IdentifyAccount(string address) + { + if (address == clientAccount.EthAddress.Address) return "Client"; + try + { + var index = hostAccounts.FindIndex(a => a.EthAddress.Address == address); + return "Host" + index; + } + catch + { + return "UNKNOWN"; + } + } + public class RewardApiCalls { private readonly CoreInterface ci;