diff --git a/ProjectPlugins/CodexClient/CodexTypes.cs b/ProjectPlugins/CodexClient/CodexTypes.cs
index 9085aa2c..f9a0d9d2 100644
--- a/ProjectPlugins/CodexClient/CodexTypes.cs
+++ b/ProjectPlugins/CodexClient/CodexTypes.cs
@@ -17,6 +17,7 @@ namespace CodexClient
{
public string Version { get; set; } = string.Empty;
public string Revision { get; set; } = string.Empty;
+ public string Contracts { get; set; } = string.Empty;
public bool IsValid()
{
diff --git a/ProjectPlugins/CodexClient/Mapper.cs b/ProjectPlugins/CodexClient/Mapper.cs
index 43bb15d0..16c156bd 100644
--- a/ProjectPlugins/CodexClient/Mapper.cs
+++ b/ProjectPlugins/CodexClient/Mapper.cs
@@ -168,7 +168,8 @@ namespace CodexClient
return new DebugInfoVersion
{
Version = obj.Version,
- Revision = obj.Revision
+ Revision = obj.Revision,
+ Contracts = obj.Contracts
};
}
diff --git a/ProjectPlugins/CodexClient/openapi.yaml b/ProjectPlugins/CodexClient/openapi.yaml
index fd66648e..d59cbcfa 100644
--- a/ProjectPlugins/CodexClient/openapi.yaml
+++ b/ProjectPlugins/CodexClient/openapi.yaml
@@ -124,6 +124,9 @@ components:
revision:
type: string
example: 0c647d8
+ contracts:
+ type: string
+ example: 0b537c7
PeersTable:
type: object
diff --git a/ProjectPlugins/CodexContractsPlugin/CodexContractsContainerRecipe.cs b/ProjectPlugins/CodexContractsPlugin/CodexContractsContainerRecipe.cs
index e09a0ee7..b46f3c96 100644
--- a/ProjectPlugins/CodexContractsPlugin/CodexContractsContainerRecipe.cs
+++ b/ProjectPlugins/CodexContractsPlugin/CodexContractsContainerRecipe.cs
@@ -1,4 +1,5 @@
-using GethPlugin;
+using CodexClient;
+using GethPlugin;
using KubernetesWorkflow;
using KubernetesWorkflow.Recipe;
@@ -8,14 +9,14 @@ namespace CodexContractsPlugin
{
public const string MarketplaceAddressFilename = "/hardhat/deployments/codexdisttestnetwork/Marketplace.json";
public const string MarketplaceArtifactFilename = "/hardhat/artifacts/contracts/Marketplace.sol/Marketplace.json";
- private readonly VersionRegistry versionRegistry;
+ private readonly DebugInfoVersion versionInfo;
public override string AppName => "codex-contracts";
- public override string Image => versionRegistry.GetContractsDockerImage();
+ public override string Image => GetContractsDockerImage();
- public CodexContractsContainerRecipe(VersionRegistry versionRegistry)
+ public CodexContractsContainerRecipe(DebugInfoVersion versionInfo)
{
- this.versionRegistry = versionRegistry;
+ this.versionInfo = versionInfo;
}
protected override void Initialize(StartupConfig startupConfig)
@@ -30,5 +31,10 @@ namespace CodexContractsPlugin
AddEnvVar("HARDHAT_NETWORK", "codexdisttestnetwork");
AddEnvVar("KEEP_ALIVE", "1");
}
+
+ private string GetContractsDockerImage()
+ {
+ return $"codexstorage/codex-contracts-eth:sha-{versionInfo.Contracts}-dist-tests";
+ }
}
}
diff --git a/ProjectPlugins/CodexContractsPlugin/CodexContractsPlugin.cs b/ProjectPlugins/CodexContractsPlugin/CodexContractsPlugin.cs
index 6e02280d..1d122d3b 100644
--- a/ProjectPlugins/CodexContractsPlugin/CodexContractsPlugin.cs
+++ b/ProjectPlugins/CodexContractsPlugin/CodexContractsPlugin.cs
@@ -7,15 +7,11 @@ namespace CodexContractsPlugin
{
private readonly IPluginTools tools;
private readonly CodexContractsStarter starter;
- private readonly VersionRegistry versionRegistry;
- private readonly CodexContractsContainerRecipe recipe;
public CodexContractsPlugin(IPluginTools tools)
{
this.tools = tools;
- versionRegistry = new VersionRegistry(tools.GetLog());
- recipe = new CodexContractsContainerRecipe(versionRegistry);
- starter = new CodexContractsStarter(tools, recipe);
+ starter = new CodexContractsStarter(tools);
}
public string LogPrefix => "(CodexContracts) ";
@@ -31,16 +27,16 @@ namespace CodexContractsPlugin
public void AddMetadata(IAddMetadata metadata)
{
- metadata.Add("codexcontractsid", recipe.Image);
+ metadata.Add("codexcontractsid", "dynamic");
}
public void Decommission()
{
}
- public CodexContractsDeployment DeployContracts(CoreInterface ci, IGethNode gethNode)
+ public CodexContractsDeployment DeployContracts(CoreInterface ci, IGethNode gethNode, CodexClient.DebugInfoVersion versionInfo)
{
- return starter.Deploy(ci, gethNode);
+ return starter.Deploy(ci, gethNode, versionInfo);
}
public ICodexContracts WrapDeploy(IGethNode gethNode, CodexContractsDeployment deployment)
@@ -48,10 +44,5 @@ namespace CodexContractsPlugin
deployment = SerializeGate.Gate(deployment);
return starter.Wrap(gethNode, deployment);
}
-
- public void SetCodexDockerImageProvider(ICodexDockerImageProvider provider)
- {
- versionRegistry.SetProvider(provider);
- }
}
}
diff --git a/ProjectPlugins/CodexContractsPlugin/CodexContractsPlugin.csproj b/ProjectPlugins/CodexContractsPlugin/CodexContractsPlugin.csproj
index 24f87068..34f6cad1 100644
--- a/ProjectPlugins/CodexContractsPlugin/CodexContractsPlugin.csproj
+++ b/ProjectPlugins/CodexContractsPlugin/CodexContractsPlugin.csproj
@@ -13,6 +13,7 @@
+
diff --git a/ProjectPlugins/CodexContractsPlugin/CodexContractsStarter.cs b/ProjectPlugins/CodexContractsPlugin/CodexContractsStarter.cs
index 5ecc22a9..c7e900be 100644
--- a/ProjectPlugins/CodexContractsPlugin/CodexContractsStarter.cs
+++ b/ProjectPlugins/CodexContractsPlugin/CodexContractsStarter.cs
@@ -1,4 +1,5 @@
-using CodexContractsPlugin.Marketplace;
+using CodexClient;
+using CodexContractsPlugin.Marketplace;
using Core;
using GethPlugin;
using KubernetesWorkflow;
@@ -12,15 +13,13 @@ namespace CodexContractsPlugin
public class CodexContractsStarter
{
private readonly IPluginTools tools;
- private readonly CodexContractsContainerRecipe recipe;
- public CodexContractsStarter(IPluginTools tools, CodexContractsContainerRecipe recipe)
+ public CodexContractsStarter(IPluginTools tools)
{
this.tools = tools;
- this.recipe = recipe;
}
- public CodexContractsDeployment Deploy(CoreInterface ci, IGethNode gethNode)
+ public CodexContractsDeployment Deploy(CoreInterface ci, IGethNode gethNode, DebugInfoVersion versionInfo)
{
Log("Starting Codex SmartContracts container...");
@@ -28,6 +27,9 @@ namespace CodexContractsPlugin
var startupConfig = CreateStartupConfig(gethNode);
startupConfig.NameOverride = "codex-contracts";
+ var recipe = new CodexContractsContainerRecipe(versionInfo);
+ Log($"Using image: {recipe.Image}");
+
var containers = workflow.Start(1, recipe, startupConfig).WaitForOnline();
if (containers.Containers.Length != 1) throw new InvalidOperationException("Expected 1 Codex contracts container to be created. Test infra failure.");
var container = containers.Containers[0];
diff --git a/ProjectPlugins/CodexContractsPlugin/CoreInterfaceExtensions.cs b/ProjectPlugins/CodexContractsPlugin/CoreInterfaceExtensions.cs
index ea123bc9..d07e25f7 100644
--- a/ProjectPlugins/CodexContractsPlugin/CoreInterfaceExtensions.cs
+++ b/ProjectPlugins/CodexContractsPlugin/CoreInterfaceExtensions.cs
@@ -1,13 +1,14 @@
-using Core;
+using CodexClient;
+using Core;
using GethPlugin;
namespace CodexContractsPlugin
{
public static class CoreInterfaceExtensions
{
- public static CodexContractsDeployment DeployCodexContracts(this CoreInterface ci, IGethNode gethNode)
+ public static CodexContractsDeployment DeployCodexContracts(this CoreInterface ci, IGethNode gethNode, DebugInfoVersion versionInfo)
{
- return Plugin(ci).DeployContracts(ci, gethNode);
+ return Plugin(ci).DeployContracts(ci, gethNode, versionInfo);
}
public static ICodexContracts WrapCodexContractsDeployment(this CoreInterface ci, IGethNode gethNode, CodexContractsDeployment deployment)
@@ -15,17 +16,12 @@ namespace CodexContractsPlugin
return Plugin(ci).WrapDeploy(gethNode, deployment);
}
- public static ICodexContracts StartCodexContracts(this CoreInterface ci, IGethNode gethNode)
+ public static ICodexContracts StartCodexContracts(this CoreInterface ci, IGethNode gethNode, DebugInfoVersion versionInfo)
{
- var deployment = DeployCodexContracts(ci, gethNode);
+ var deployment = DeployCodexContracts(ci, gethNode, versionInfo);
return WrapCodexContractsDeployment(ci, gethNode, deployment);
}
- public static void SetCodexDockerImageProvider(this CoreInterface ci, ICodexDockerImageProvider provider)
- {
- Plugin(ci).SetCodexDockerImageProvider(provider);
- }
-
private static CodexContractsPlugin Plugin(CoreInterface ci)
{
return ci.GetPlugin();
diff --git a/ProjectPlugins/CodexContractsPlugin/VersionRegistry.cs b/ProjectPlugins/CodexContractsPlugin/VersionRegistry.cs
deleted file mode 100644
index f52a38a8..00000000
--- a/ProjectPlugins/CodexContractsPlugin/VersionRegistry.cs
+++ /dev/null
@@ -1,125 +0,0 @@
-using System.Diagnostics;
-using Logging;
-
-namespace CodexContractsPlugin
-{
- public interface ICodexDockerImageProvider
- {
- string GetCodexDockerImage();
- }
-
- public class VersionRegistry
- {
- private ICodexDockerImageProvider provider = new ExceptionProvider();
- private static readonly Dictionary cache = new Dictionary();
- private static readonly object cacheLock = new object();
- private readonly ILog log;
-
- public VersionRegistry(ILog log)
- {
- this.log = log;
- }
-
- public void SetProvider(ICodexDockerImageProvider provider)
- {
- this.provider = provider;
- }
-
- public string GetContractsDockerImage()
- {
- try
- {
- var codexImage = provider.GetCodexDockerImage();
- return GetContractsDockerImage(codexImage);
- }
- catch (Exception exc)
- {
- throw new Exception("Failed to get contracts docker image.", exc);
- }
- }
-
- private string GetContractsDockerImage(string codexImage)
- {
- lock (cacheLock)
- {
- if (cache.TryGetValue(codexImage, out string? value))
- {
- return value;
- }
- var result = GetContractsImage(codexImage);
- cache.Add(codexImage, result);
- return result;
- }
- }
-
- private string GetContractsImage(string codexImage)
- {
- var inspectResult = InspectCodexImage(codexImage);
- var image = ParseCodexContractsImageName(inspectResult);
- log.Log($"From codex docker image '{codexImage}', determined codex-contracts docker image: '{image}'");
- return image;
- }
-
- private string InspectCodexImage(string img)
- {
- Execute("docker", $"pull {img}");
- return Execute("docker", $"inspect {img}");
- }
-
- private string ParseCodexContractsImageName(string inspectResult)
- {
- // It is a nice json structure. But we only need this one line.
- // "storage.codex.nim-codex.blockchain-image": "codexstorage/codex-contracts-eth:sha-0bf1385-dist-tests"
- var lines = inspectResult.Split('\n', StringSplitOptions.RemoveEmptyEntries);
- var line = lines.Single(l => l.Contains("storage.codex.nim-codex.blockchain-image"));
- var tokens = line.Split(' ', StringSplitOptions.RemoveEmptyEntries);
- return tokens.Last().Replace("\"", "").Trim();
- }
-
- private string Execute(string cmd, string args)
- {
- var startInfo = new ProcessStartInfo(
- fileName: cmd,
- arguments: args
- );
- startInfo.RedirectStandardOutput = true;
- startInfo.RedirectStandardError = true;
-
- var process = Process.Start(startInfo);
- if (process == null)
- {
- throw new Exception("Failed to start: " + cmd + args);
- }
- KillAfterTimeout(process);
-
- process.WaitForExit();
- return process.StandardOutput.ReadToEnd();
- }
-
- private void KillAfterTimeout(Process process)
- {
- // There's a known issue that some docker commands on some platforms
- // will fail to stop on their own. This has been known since 2019 and it's not fixed.
- // So we will issue a kill to the process ourselves if it exceeds a timeout.
-
- Task.Run(() =>
- {
- Thread.Sleep(TimeSpan.FromSeconds(30.0));
-
- if (process != null && !process.HasExited)
- {
- process.Kill();
- }
- });
- }
- }
-
- internal class ExceptionProvider : ICodexDockerImageProvider
- {
- public string GetCodexDockerImage()
- {
- throw new InvalidOperationException("CodexContractsPlugin has not yet received a CodexDockerImageProvider " +
- "and so cannot select a compatible contracts docker image.");
- }
- }
-}
diff --git a/ProjectPlugins/CodexPlugin/ApiChecker.cs b/ProjectPlugins/CodexPlugin/ApiChecker.cs
index 656c6588..4b190b34 100644
--- a/ProjectPlugins/CodexPlugin/ApiChecker.cs
+++ b/ProjectPlugins/CodexPlugin/ApiChecker.cs
@@ -10,7 +10,7 @@ namespace CodexPlugin
public class ApiChecker
{
//
- private const string OpenApiYamlHash = "1A-F7-DF-C3-E1-C6-98-FF-32-20-21-9B-26-40-B0-51-08-35-C2-E7-DB-41-49-93-60-A9-CE-47-B5-AD-3D-A3";
+ private const string OpenApiYamlHash = "06-B9-41-E8-C8-6C-DE-01-86-83-F3-9A-E4-AC-E7-30-D9-E6-64-60-E0-21-81-9E-4E-C5-93-77-2C-71-79-14";
private const string OpenApiFilePath = "/codex/openapi.yaml";
private const string DisableEnvironmentVariable = "CODEXPLUGIN_DISABLE_APICHECK";
diff --git a/ProjectPlugins/CodexPlugin/CodexDockerImage.cs b/ProjectPlugins/CodexPlugin/CodexDockerImage.cs
index 5ed36c92..bbb09c0b 100644
--- a/ProjectPlugins/CodexPlugin/CodexDockerImage.cs
+++ b/ProjectPlugins/CodexPlugin/CodexDockerImage.cs
@@ -1,8 +1,6 @@
-using CodexContractsPlugin;
-
-namespace CodexPlugin
+namespace CodexPlugin
{
- public class CodexDockerImage : ICodexDockerImageProvider
+ public class CodexDockerImage
{
private const string DefaultDockerImage = "codexstorage/nim-codex:latest-dist-tests";
diff --git a/ProjectPlugins/CodexPlugin/CodexPlugin.cs b/ProjectPlugins/CodexPlugin/CodexPlugin.cs
index 277b6101..0c8f4510 100644
--- a/ProjectPlugins/CodexPlugin/CodexPlugin.cs
+++ b/ProjectPlugins/CodexPlugin/CodexPlugin.cs
@@ -42,7 +42,6 @@ namespace CodexPlugin
public void Awake(IPluginAccess access)
{
- access.GetPlugin().SetCodexDockerImageProvider(codexDockerImage);
}
public void Announce()
diff --git a/Tests/CodexReleaseTests/DataTests/DataExpiryTest.cs b/Tests/CodexReleaseTests/DataTests/DataExpiryTest.cs
index 263a9e8b..4b9139e6 100644
--- a/Tests/CodexReleaseTests/DataTests/DataExpiryTest.cs
+++ b/Tests/CodexReleaseTests/DataTests/DataExpiryTest.cs
@@ -50,8 +50,9 @@ namespace CodexReleaseTests.DataTests
var blockTtl = TimeSpan.FromMinutes(1.0);
var interval = TimeSpan.FromSeconds(10.0);
+ var bootstrapNode = StartCodex();
var geth = StartGethNode(s => s.IsMiner());
- var contracts = Ci.StartCodexContracts(geth);
+ var contracts = Ci.StartCodexContracts(geth, bootstrapNode.Version);
var node = StartCodex(s => s
.EnableMarketplace(geth, contracts, m => m.WithInitial(100.Eth(), 100.Tst()))
.WithBlockTTL(blockTtl)
diff --git a/Tests/CodexReleaseTests/MarketTests/MarketplaceAutoBootstrapDistTest.cs b/Tests/CodexReleaseTests/MarketTests/MarketplaceAutoBootstrapDistTest.cs
index e6711e34..a5ec0885 100644
--- a/Tests/CodexReleaseTests/MarketTests/MarketplaceAutoBootstrapDistTest.cs
+++ b/Tests/CodexReleaseTests/MarketTests/MarketplaceAutoBootstrapDistTest.cs
@@ -6,7 +6,6 @@ using CodexTests;
using DistTestCore;
using GethPlugin;
using Nethereum.Hex.HexConvertors.Extensions;
-using NUnit.Framework;
using Utils;
namespace CodexReleaseTests.MarketTests
@@ -21,14 +20,14 @@ namespace CodexReleaseTests.MarketTests
{
base.LifecycleStart(lifecycle);
var geth = StartGethNode(s => s.IsMiner());
- var contracts = Ci.StartCodexContracts(geth);
+ var contracts = Ci.StartCodexContracts(geth, BootstrapNode.Version);
handles.Add(lifecycle, new MarketplaceHandle(geth, contracts));
}
protected override void LifecycleStop(TestLifecycle lifecycle, DistTestResult result)
{
- base.LifecycleStop(lifecycle, result);
handles.Remove(lifecycle);
+ base.LifecycleStop(lifecycle, result);
}
protected IGethNode GetGeth()
diff --git a/Tests/ExperimentalTests/AutoBootstrapDistTest.cs b/Tests/ExperimentalTests/AutoBootstrapDistTest.cs
index d39c31ec..d8ac6805 100644
--- a/Tests/ExperimentalTests/AutoBootstrapDistTest.cs
+++ b/Tests/ExperimentalTests/AutoBootstrapDistTest.cs
@@ -1,37 +1,40 @@
using CodexClient;
using CodexPlugin;
using DistTestCore;
-using NUnit.Framework;
namespace CodexTests
{
public class AutoBootstrapDistTest : CodexDistTest
{
private readonly Dictionary bootstrapNodes = new Dictionary();
+ private bool isBooting = false;
- [SetUp]
- public void SetUpBootstrapNode()
+ protected override void LifecycleStart(TestLifecycle tl)
{
- var tl = Get();
+ base.LifecycleStart(tl);
if (!bootstrapNodes.ContainsKey(tl))
{
+ isBooting = true;
bootstrapNodes.Add(tl, StartCodex(s => s.WithName("BOOTSTRAP_" + tl.TestNamespace)));
+ isBooting = false;
}
}
- [TearDown]
- public void TearDownBootstrapNode()
+ protected override void LifecycleStop(TestLifecycle lifecycle, DistTestResult result)
{
- bootstrapNodes.Remove(Get());
+ bootstrapNodes.Remove(lifecycle);
+ base.LifecycleStop(lifecycle, result);
}
protected override void OnCodexSetup(ICodexSetup setup)
{
+ if (isBooting) return;
+
var node = BootstrapNode;
if (node != null) setup.WithBootstrapNode(node);
}
- protected ICodexNode? BootstrapNode
+ protected ICodexNode BootstrapNode
{
get
{
@@ -40,7 +43,7 @@ namespace CodexTests
{
return node;
}
- return null;
+ throw new InvalidOperationException("Bootstrap node not yet started.");
}
}
}
diff --git a/Tests/ExperimentalTests/BasicTests/MarketplaceTests.cs b/Tests/ExperimentalTests/BasicTests/MarketplaceTests.cs
index f8ef52d5..af213342 100644
--- a/Tests/ExperimentalTests/BasicTests/MarketplaceTests.cs
+++ b/Tests/ExperimentalTests/BasicTests/MarketplaceTests.cs
@@ -31,7 +31,7 @@ namespace ExperimentalTests.BasicTests
);
var geth = StartGethNode(s => s.IsMiner().WithName("disttest-geth"));
- var contracts = Ci.StartCodexContracts(geth);
+ var contracts = Ci.StartCodexContracts(geth, BootstrapNode.Version);
var numberOfHosts = 5;
var hosts = StartCodex(numberOfHosts, s => s
diff --git a/Tests/ExperimentalTests/DownloadConnectivityTests/FullyConnectedDownloadTests.cs b/Tests/ExperimentalTests/DownloadConnectivityTests/FullyConnectedDownloadTests.cs
index ec128154..d0acc991 100644
--- a/Tests/ExperimentalTests/DownloadConnectivityTests/FullyConnectedDownloadTests.cs
+++ b/Tests/ExperimentalTests/DownloadConnectivityTests/FullyConnectedDownloadTests.cs
@@ -21,7 +21,7 @@ namespace ExperimentalTests.DownloadConnectivityTests
public void MarketplaceDoesNotInterfereWithPeerDownload()
{
var geth = StartGethNode(s => s.IsMiner());
- var contracts = Ci.StartCodexContracts(geth);
+ var contracts = Ci.StartCodexContracts(geth, BootstrapNode.Version);
var nodes = StartCodex(2, s => s.EnableMarketplace(geth, contracts, m => m
.WithInitial(10.Eth(), 1000.TstWei())));
diff --git a/Tests/ExperimentalTests/PeerDiscoveryTests/PeerDiscoveryTests.cs b/Tests/ExperimentalTests/PeerDiscoveryTests/PeerDiscoveryTests.cs
index 901504c7..60a9be9a 100644
--- a/Tests/ExperimentalTests/PeerDiscoveryTests/PeerDiscoveryTests.cs
+++ b/Tests/ExperimentalTests/PeerDiscoveryTests/PeerDiscoveryTests.cs
@@ -31,7 +31,7 @@ namespace ExperimentalTests.PeerDiscoveryTests
public void MarketplaceDoesNotInterfereWithPeerDiscovery()
{
var geth = StartGethNode(s => s.IsMiner());
- var contracts = Ci.StartCodexContracts(geth);
+ var contracts = Ci.StartCodexContracts(geth, BootstrapNode.Version);
var nodes = StartCodex(2, s => s.EnableMarketplace(geth, contracts, m => m
.WithInitial(10.Eth(), 1000.TstWei())));
diff --git a/Tools/CodexNetDeployer/Deployer.cs b/Tools/CodexNetDeployer/Deployer.cs
index 753a1371..0d78962e 100644
--- a/Tools/CodexNetDeployer/Deployer.cs
+++ b/Tools/CodexNetDeployer/Deployer.cs
@@ -64,8 +64,12 @@ namespace CodexNetDeployer
var gethDeployment = DeployGeth(ci);
var gethNode = ci.WrapGethDeployment(gethDeployment, new BlockCache());
+ var bootNode = ci.StartCodexNode();
+ var versionInfo = bootNode.GetDebugInfo().Version;
+ bootNode.Stop(waitTillStopped: true);
+
Log("Geth started. Deploying Codex contracts...");
- var contractsDeployment = ci.DeployCodexContracts(gethNode);
+ var contractsDeployment = ci.DeployCodexContracts(gethNode, versionInfo);
var contracts = ci.WrapCodexContractsDeployment(gethNode, contractsDeployment);
Log("Codex contracts deployed.");