Can start Geth

This commit is contained in:
ThatBen 2023-09-15 15:52:02 +02:00
parent f2a8c123a5
commit 4cc93eba73
17 changed files with 428 additions and 343 deletions

View File

@ -1,6 +1,4 @@
//using DistTestCore.Marketplace; using KubernetesWorkflow;
using Core;
using KubernetesWorkflow;
using Utils; using Utils;
namespace CodexPlugin namespace CodexPlugin

View File

@ -0,0 +1,147 @@
using KubernetesWorkflow;
using Logging;
using Utils;
namespace GethPlugin
{
public class ContainerInfoExtractor
{
private readonly ILog log;
private readonly IStartupWorkflow workflow;
private readonly RunningContainer container;
public ContainerInfoExtractor(ILog log, IStartupWorkflow workflow, RunningContainer container)
{
this.log = log;
this.workflow = workflow;
this.container = container;
}
public AllGethAccounts ExtractAccounts()
{
log.Debug();
var accountsCsv = Retry(() => FetchAccountsCsv());
if (string.IsNullOrEmpty(accountsCsv)) throw new InvalidOperationException("Unable to fetch accounts.csv for geth node. Test infra failure.");
var lines = accountsCsv.Split('\n');
return new AllGethAccounts(lines.Select(ParseLineToAccount).ToArray());
}
public string ExtractPubKey()
{
log.Debug();
var pubKey = Retry(FetchPubKey);
if (string.IsNullOrEmpty(pubKey)) throw new InvalidOperationException("Unable to fetch enode from geth node. Test infra failure.");
return pubKey;
}
//public string ExtractMarketplaceAddress()
//{
// log.Debug();
// var marketplaceAddress = Retry(FetchMarketplaceAddress);
// if (string.IsNullOrEmpty(marketplaceAddress)) throw new InvalidOperationException("Unable to fetch marketplace account from codex-contracts node. Test infra failure.");
// return marketplaceAddress;
//}
//public string ExtractMarketplaceAbi()
//{
// log.Debug();
// var marketplaceAbi = Retry(FetchMarketplaceAbi);
// if (string.IsNullOrEmpty(marketplaceAbi)) throw new InvalidOperationException("Unable to fetch marketplace artifacts from codex-contracts node. Test infra failure.");
// return marketplaceAbi;
//}
private string FetchAccountsCsv()
{
return workflow.ExecuteCommand(container, "cat", GethContainerRecipe.AccountsFilename);
}
//private string FetchMarketplaceAddress()
//{
// var json = workflow.ExecuteCommand(container, "cat", CodexContractsContainerRecipe.MarketplaceAddressFilename);
// var marketplace = JsonConvert.DeserializeObject<MarketplaceJson>(json);
// return marketplace!.address;
//}
//private string FetchMarketplaceAbi()
//{
// var json = workflow.ExecuteCommand(container, "cat", CodexContractsContainerRecipe.MarketplaceArtifactFilename);
// var artifact = JObject.Parse(json);
// var abi = artifact["abi"];
// return abi!.ToString(Formatting.None);
//}
private string FetchPubKey()
{
var enodeFinder = new PubKeyFinder(s => log.Debug(s));
workflow.DownloadContainerLog(container, enodeFinder, null);
return enodeFinder.GetPubKey();
}
private GethAccount ParseLineToAccount(string l)
{
var tokens = l.Replace("\r", "").Split(',');
if (tokens.Length != 2) throw new InvalidOperationException();
var account = tokens[0];
var privateKey = tokens[1];
return new GethAccount(account, privateKey);
}
private static string Retry(Func<string> fetch)
{
return Time.Retry(fetch, nameof(ContainerInfoExtractor));
}
}
public class PubKeyFinder : LogHandler, ILogHandler
{
private const string openTag = "self=enode://";
private const string openTagQuote = "self=\"enode://";
private readonly Action<string> debug;
private string pubKey = string.Empty;
public PubKeyFinder(Action<string> debug)
{
this.debug = debug;
debug($"Looking for '{openTag}' in container logs...");
}
public string GetPubKey()
{
if (string.IsNullOrEmpty(pubKey)) throw new Exception("Not found yet exception.");
return pubKey;
}
protected override void ProcessLine(string line)
{
debug(line);
if (line.Contains(openTag))
{
ExtractPubKey(openTag, line);
}
else if (line.Contains(openTagQuote))
{
ExtractPubKey(openTagQuote, line);
}
}
private void ExtractPubKey(string tag, string line)
{
var openIndex = line.IndexOf(tag) + tag.Length;
var closeIndex = line.IndexOf("@");
pubKey = line.Substring(
startIndex: openIndex,
length: closeIndex - openIndex);
}
}
//public class MarketplaceJson
//{
// public string address { get; set; } = string.Empty;
//}
}

View File

@ -1,44 +1,17 @@
using Core; using Core;
using KubernetesWorkflow;
namespace GethPlugin namespace GethPlugin
{ {
public static class CoreInterfaceExtensions public static class CoreInterfaceExtensions
{ {
//public static RunningContainers[] StartCodexNodes(this CoreInterface ci, int number, Action<ICodexSetup> setup) public static IGethNodeInfo StartGethNode(this CoreInterface ci, Action<IGethSetup> setup)
//{ {
// return Plugin(ci).StartCodexNodes(number, setup); return Plugin(ci).StartGeth(setup);
//} }
//public static ICodexNodeGroup WrapCodexContainers(this CoreInterface ci, RunningContainers[] containers) private static GethPlugin Plugin(CoreInterface ci)
//{ {
// return Plugin(ci).WrapCodexContainers(containers); return ci.GetPlugin<GethPlugin>();
//} }
//public static IOnlineCodexNode SetupCodexNode(this CoreInterface ci)
//{
// return ci.SetupCodexNodes(1)[0];
//}
//public static IOnlineCodexNode SetupCodexNode(this CoreInterface ci, Action<ICodexSetup> setup)
//{
// return ci.SetupCodexNodes(1, setup)[0];
//}
//public static ICodexNodeGroup SetupCodexNodes(this CoreInterface ci, int number, Action<ICodexSetup> setup)
//{
// var rc = ci.StartCodexNodes(number, setup);
// return ci.WrapCodexContainers(rc);
//}
//public static ICodexNodeGroup SetupCodexNodes(this CoreInterface ci, int number)
//{
// return ci.SetupCodexNodes(number, s => { });
//}
//private static CodexPlugin Plugin(CoreInterface ci)
//{
// return ci.GetPlugin<CodexPlugin>();
//}
} }
} }

24
GethPlugin/GethAccount.cs Normal file
View File

@ -0,0 +1,24 @@
namespace GethPlugin
{
public class GethAccount
{
public GethAccount(string account, string privateKey)
{
Account = account;
PrivateKey = privateKey;
}
public string Account { get; }
public string PrivateKey { get; }
}
public class AllGethAccounts
{
public GethAccount[] Accounts { get; }
public AllGethAccounts(GethAccount[] accounts)
{
Accounts = accounts;
}
}
}

View File

@ -1,42 +0,0 @@
using KubernetesWorkflow;
using NethereumWorkflow;
namespace GethPlugin
{
public class GethBootstrapNodeInfo
{
public GethBootstrapNodeInfo(RunningContainers runningContainers, AllGethAccounts allAccounts, string pubKey, Port discoveryPort)
{
RunningContainers = runningContainers;
AllAccounts = allAccounts;
Account = allAccounts.Accounts[0];
PubKey = pubKey;
DiscoveryPort = discoveryPort;
}
public RunningContainers RunningContainers { get; }
public AllGethAccounts AllAccounts { get; }
public GethAccount Account { get; }
public string PubKey { get; }
public Port DiscoveryPort { get; }
public NethereumInteraction StartInteraction(TestLifecycle lifecycle)
{
var address = lifecycle.Configuration.GetAddress(RunningContainers.Containers[0]);
var account = Account;
var creator = new NethereumInteractionCreator(lifecycle.Log, address.Host, address.Port, account.PrivateKey);
return creator.CreateWorkflow();
}
}
public class AllGethAccounts
{
public GethAccount[] Accounts { get; }
public AllGethAccounts(GethAccount[] accounts)
{
Accounts = accounts;
}
}
}

View File

@ -1,35 +0,0 @@
using KubernetesWorkflow;
namespace GethPlugin
{
public class GethBootstrapNodeStarter
{
public GethBootstrapNodeInfo StartGethBootstrapNode()
{
LogStart("Starting Geth bootstrap node...");
var startupConfig = CreateBootstrapStartupConfig();
var workflow = lifecycle.WorkflowCreator.CreateWorkflow();
var containers = workflow.Start(1, Location.Unspecified, new GethContainerRecipe(), startupConfig);
if (containers.Containers.Length != 1) throw new InvalidOperationException("Expected 1 Geth bootstrap node to be created. Test infra failure.");
var bootstrapContainer = containers.Containers[0];
var extractor = new ContainerInfoExtractor(lifecycle.Log, workflow, bootstrapContainer);
var accounts = extractor.ExtractAccounts();
var pubKey = extractor.ExtractPubKey();
var discoveryPort = bootstrapContainer.Recipe.GetPortByTag(GethContainerRecipe.DiscoveryPortTag);
var result = new GethBootstrapNodeInfo(containers, accounts, pubKey, discoveryPort);
LogEnd($"Geth bootstrap node started with account '{result.Account.Account}'");
return result;
}
private StartupConfig CreateBootstrapStartupConfig()
{
var config = new StartupConfig();
config.Add(new GethStartupConfig(true, null!, 0, 0));
return config;
}
}
}

View File

@ -1,38 +1,26 @@
using KubernetesWorkflow; //using KubernetesWorkflow;
using NethereumWorkflow; //using NethereumWorkflow;
namespace GethPlugin //namespace GethPlugin
{ //{
public class GethCompanionNodeInfo // public class GethCompanionNodeInfo
{ // {
public GethCompanionNodeInfo(RunningContainer runningContainer, GethAccount[] accounts) // public GethCompanionNodeInfo(RunningContainer runningContainer, GethAccount[] accounts)
{ // {
RunningContainer = runningContainer; // RunningContainer = runningContainer;
Accounts = accounts; // Accounts = accounts;
} // }
public RunningContainer RunningContainer { get; } // public RunningContainer RunningContainer { get; }
public GethAccount[] Accounts { get; } // public GethAccount[] Accounts { get; }
public NethereumInteraction StartInteraction(TestLifecycle lifecycle, GethAccount account) // public NethereumInteraction StartInteraction(TestLifecycle lifecycle, GethAccount account)
{ // {
var address = lifecycle.Configuration.GetAddress(RunningContainer); // var address = lifecycle.Configuration.GetAddress(RunningContainer);
var privateKey = account.PrivateKey; // var privateKey = account.PrivateKey;
var creator = new NethereumInteractionCreator(lifecycle.Log, address.Host, address.Port, privateKey); // var creator = new NethereumInteractionCreator(lifecycle.Log, address.Host, address.Port, privateKey);
return creator.CreateWorkflow(); // return creator.CreateWorkflow();
} // }
} // }
//}
public class GethAccount
{
public GethAccount(string account, string privateKey)
{
Account = account;
PrivateKey = privateKey;
}
public string Account { get; }
public string PrivateKey { get; }
}
}

View File

@ -1,72 +0,0 @@
using KubernetesWorkflow;
using Utils;
namespace GethPlugin
{
public class GethCompanionNodeStarter
{
private int companionAccountIndex = 0;
public GethCompanionNodeInfo StartCompanionNodeFor(CodexSetup codexSetup, MarketplaceNetwork marketplace)
{
LogStart($"Initializing companion for {codexSetup.NumberOfNodes} Codex nodes.");
var config = CreateCompanionNodeStartupConfig(marketplace.Bootstrap, codexSetup.NumberOfNodes);
var workflow = lifecycle.WorkflowCreator.CreateWorkflow();
var containers = workflow.Start(1, Location.Unspecified, new GethContainerRecipe(), CreateStartupConfig(config));
if (containers.Containers.Length != 1) throw new InvalidOperationException("Expected one Geth companion node to be created. Test infra failure.");
var container = containers.Containers[0];
var node = CreateCompanionInfo(container, marketplace, config);
EnsureCompanionNodeIsSynced(node, marketplace);
LogEnd($"Initialized one companion node for {codexSetup.NumberOfNodes} Codex nodes. Their accounts: [{string.Join(",", node.Accounts.Select(a => a.Account))}]");
return node;
}
private GethCompanionNodeInfo CreateCompanionInfo(RunningContainer container, MarketplaceNetwork marketplace, GethStartupConfig config)
{
var accounts = ExtractAccounts(marketplace, config);
return new GethCompanionNodeInfo(container, accounts);
}
private static GethAccount[] ExtractAccounts(MarketplaceNetwork marketplace, GethStartupConfig config)
{
return marketplace.Bootstrap.AllAccounts.Accounts
.Skip(1 + config.CompanionAccountStartIndex)
.Take(config.NumberOfCompanionAccounts)
.ToArray();
}
private void EnsureCompanionNodeIsSynced(GethCompanionNodeInfo node, MarketplaceNetwork marketplace)
{
try
{
Time.WaitUntil(() =>
{
var interaction = node.StartInteraction(lifecycle, node.Accounts.First());
return interaction.IsSynced(marketplace.Marketplace.Address, marketplace.Marketplace.Abi);
}, TimeSpan.FromMinutes(1), TimeSpan.FromSeconds(3));
}
catch (Exception e)
{
throw new Exception("Geth companion node did not sync within timeout. Test infra failure.", e);
}
}
private GethStartupConfig CreateCompanionNodeStartupConfig(GethBootstrapNodeInfo bootstrapNode, int numberOfAccounts)
{
var config = new GethStartupConfig(false, bootstrapNode, companionAccountIndex, numberOfAccounts);
companionAccountIndex += numberOfAccounts;
return config;
}
private StartupConfig CreateStartupConfig(GethStartupConfig gethConfig)
{
var config = new StartupConfig();
config.Add(gethConfig);
return config;
}
}
}

View File

@ -26,38 +26,23 @@ namespace GethPlugin
{ {
var discovery = AddInternalPort(tag: DiscoveryPortTag); var discovery = AddInternalPort(tag: DiscoveryPortTag);
if (config.IsBootstrapNode) if (config.IsMiner) AddEnvVar("ENABLE_MINER", "1");
{
return CreateBootstapArgs(discovery);
}
return CreateCompanionArgs(discovery, config);
}
private string CreateBootstapArgs(Port discovery)
{
AddEnvVar("ENABLE_MINER", "1");
UnlockAccounts(0, 1); UnlockAccounts(0, 1);
var exposedPort = AddExposedPort(tag: HttpPortTag); var exposedPort = AddExposedPort(tag: HttpPortTag);
return $"--http.port {exposedPort.Number} --port {discovery.Number} --discovery.port {discovery.Number} {defaultArgs}"; var args = $"--http.addr 0.0.0.0 --http.port {exposedPort.Number} --port {discovery.Number} --discovery.port {discovery.Number} {defaultArgs}";
var authRpc = AddInternalPort();
if (config.BootstrapNode != null)
{
var bootPubKey = config.BootstrapNode.PublicKey;
var bootIp = config.BootstrapNode.IpAddress;
var bootPort = config.BootstrapNode.Port;
var bootstrapArg = $" --bootnodes enode://{bootPubKey}@{bootIp}:{bootPort} --nat=extip:{bootIp}";
args += bootstrapArg;
} }
private string CreateCompanionArgs(Port discovery, GethStartupConfig config) return args + $" --authrpc.port {authRpc.Number} --ws --ws.addr 0.0.0.0 --ws.port {exposedPort.Number}";
{
UnlockAccounts(
config.CompanionAccountStartIndex + 1,
config.NumberOfCompanionAccounts);
var port = AddInternalPort();
var authRpc = AddInternalPort();
var httpPort = AddExposedPort(tag: HttpPortTag);
var bootPubKey = config.BootstrapNode.PubKey;
var bootIp = config.BootstrapNode.RunningContainers.Containers[0].Pod.PodInfo.Ip;
var bootPort = config.BootstrapNode.DiscoveryPort.Number;
var bootstrapArg = $"--bootnodes enode://{bootPubKey}@{bootIp}:{bootPort} --nat=extip:{bootIp}";
return $"--port {port.Number} --discovery.port {discovery.Number} --authrpc.port {authRpc.Number} --http.addr 0.0.0.0 --http.port {httpPort.Number} --ws --ws.addr 0.0.0.0 --ws.port {httpPort.Number} {bootstrapArg} {defaultArgs}";
} }
private void UnlockAccounts(int startIndex, int numberOfAccounts) private void UnlockAccounts(int startIndex, int numberOfAccounts)

View File

@ -0,0 +1,35 @@
using KubernetesWorkflow;
namespace GethPlugin
{
public interface IGethNodeInfo
{
}
public class GethNodeInfo : IGethNodeInfo
{
public GethNodeInfo(RunningContainer runningContainer, AllGethAccounts allAccounts, string pubKey, Port discoveryPort)
{
RunningContainer = runningContainer;
AllAccounts = allAccounts;
Account = allAccounts.Accounts[0];
PubKey = pubKey;
DiscoveryPort = discoveryPort;
}
public RunningContainer RunningContainer { get; }
public AllGethAccounts AllAccounts { get; }
public GethAccount Account { get; }
public string PubKey { get; }
public Port DiscoveryPort { get; }
//public NethereumInteraction StartInteraction(TestLifecycle lifecycle)
//{
// var address = lifecycle.Configuration.GetAddress(RunningContainers.Containers[0]);
// var account = Account;
// var creator = new NethereumInteractionCreator(lifecycle.Log, address.Host, address.Port, account.PrivateKey);
// return creator.CreateWorkflow();
//}
}
}

View File

@ -6,11 +6,12 @@ namespace GethPlugin
public class GethPlugin : IProjectPlugin, IHasLogPrefix, IHasMetadata public class GethPlugin : IProjectPlugin, IHasLogPrefix, IHasMetadata
{ {
private readonly IPluginTools tools; private readonly IPluginTools tools;
private readonly GethStarter starter;
public GethPlugin(IPluginTools tools) public GethPlugin(IPluginTools tools)
{ {
//codexStarter = new CodexStarter(tools);
this.tools = tools; this.tools = tools;
starter = new GethStarter(tools);
} }
public string LogPrefix => "(Geth) "; public string LogPrefix => "(Geth) ";
@ -29,6 +30,13 @@ namespace GethPlugin
{ {
} }
public IGethNodeInfo StartGeth(Action<IGethSetup> setup)
{
var startupConfig = new GethStartupConfig();
setup(startupConfig);
return starter.StartGeth(startupConfig);
}
//public RunningContainers[] StartCodexNodes(int numberOfNodes, Action<ICodexSetup> setup) //public RunningContainers[] StartCodexNodes(int numberOfNodes, Action<ICodexSetup> setup)
//{ //{
// var codexSetup = new CodexSetup(numberOfNodes); // var codexSetup = new CodexSetup(numberOfNodes);

View File

@ -1,19 +1,19 @@
using Newtonsoft.Json; //using Newtonsoft.Json;
namespace GethPlugin //namespace GethPlugin
{ //{
public class GethStartResult // public class GethStartResult
{ // {
public GethStartResult(IMarketplaceAccessFactory marketplaceAccessFactory, MarketplaceNetwork marketplaceNetwork, GethCompanionNodeInfo companionNode) // public GethStartResult(IMarketplaceAccessFactory marketplaceAccessFactory, MarketplaceNetwork marketplaceNetwork, GethCompanionNodeInfo companionNode)
{ // {
MarketplaceAccessFactory = marketplaceAccessFactory; // MarketplaceAccessFactory = marketplaceAccessFactory;
MarketplaceNetwork = marketplaceNetwork; // MarketplaceNetwork = marketplaceNetwork;
CompanionNode = companionNode; // CompanionNode = companionNode;
} // }
[JsonIgnore] // [JsonIgnore]
public IMarketplaceAccessFactory MarketplaceAccessFactory { get; } // public IMarketplaceAccessFactory MarketplaceAccessFactory { get; }
public MarketplaceNetwork MarketplaceNetwork { get; } // public MarketplaceNetwork MarketplaceNetwork { get; }
public GethCompanionNodeInfo CompanionNode { get; } // public GethCompanionNodeInfo CompanionNode { get; }
} // }
} //}

View File

@ -1,86 +1,121 @@
namespace CodexPlugin using Core;
using KubernetesWorkflow;
namespace GethPlugin
{ {
public class GethStarter public class GethStarter
{ {
private readonly MarketplaceNetworkCache marketplaceNetworkCache; private readonly IPluginTools tools;
private readonly GethCompanionNodeStarter companionNodeStarter;
public GethStarter(TestLifecycle lifecycle) //private readonly MarketplaceNetworkCache marketplaceNetworkCache;
: base(lifecycle) //private readonly GethCompanionNodeStarter companionNodeStarter;
public GethStarter(IPluginTools tools)
{ {
marketplaceNetworkCache = new MarketplaceNetworkCache( this.tools = tools;
new GethBootstrapNodeStarter(lifecycle), //marketplaceNetworkCache = new MarketplaceNetworkCache(
new CodexContractsStarter(lifecycle)); // new GethBootstrapNodeStarter(lifecycle),
companionNodeStarter = new GethCompanionNodeStarter(lifecycle); // new CodexContractsStarter(lifecycle));
//companionNodeStarter = new GethCompanionNodeStarter(lifecycle);
} }
public GethStartResult BringOnlineMarketplaceFor(CodexSetup codexSetup) public IGethNodeInfo StartGeth(GethStartupConfig gethStartupConfig)
{ {
if (codexSetup.MarketplaceConfig == null) return CreateMarketplaceUnavailableResult(); Log("Starting Geth bootstrap node...");
var marketplaceNetwork = marketplaceNetworkCache.Get(); var startupConfig = new StartupConfig();
var companionNode = StartCompanionNode(codexSetup, marketplaceNetwork); startupConfig.Add(gethStartupConfig);
startupConfig.NameOverride = gethStartupConfig.NameOverride;
LogStart("Setting up initial balance..."); var workflow = tools.CreateWorkflow();
TransferInitialBalance(marketplaceNetwork, codexSetup.MarketplaceConfig, companionNode); var containers = workflow.Start(1, Location.Unspecified, new GethContainerRecipe(), startupConfig);
LogEnd($"Initial balance of {codexSetup.MarketplaceConfig.InitialTestTokens} set for {codexSetup.NumberOfNodes} nodes."); if (containers.Containers.Length != 1) throw new InvalidOperationException("Expected 1 Geth bootstrap node to be created. Test infra failure.");
var container = containers.Containers[0];
return CreateGethStartResult(marketplaceNetwork, companionNode); var extractor = new ContainerInfoExtractor(tools.GetLog(), workflow, container);
var accounts = extractor.ExtractAccounts();
var pubKey = extractor.ExtractPubKey();
var discoveryPort = container.Recipe.GetPortByTag(GethContainerRecipe.DiscoveryPortTag);
if (discoveryPort == null) throw new Exception("Expected discovery port to be created.");
var result = new GethNodeInfo(container, accounts, pubKey, discoveryPort);
Log($"Geth bootstrap node started with account '{result.Account.Account}'");
return result;
} }
private void TransferInitialBalance(MarketplaceNetwork marketplaceNetwork, MarketplaceInitialConfig marketplaceConfig, GethCompanionNodeInfo companionNode) private void Log(string msg)
{ {
if (marketplaceConfig.InitialTestTokens.Amount == 0) return; tools.GetLog().Log(msg);
var interaction = marketplaceNetwork.StartInteraction(lifecycle);
var tokenAddress = marketplaceNetwork.Marketplace.TokenAddress;
var accounts = companionNode.Accounts.Select(a => a.Account).ToArray();
interaction.MintTestTokens(accounts, marketplaceConfig.InitialTestTokens.Amount, tokenAddress);
} }
private GethStartResult CreateGethStartResult(MarketplaceNetwork marketplaceNetwork, GethCompanionNodeInfo companionNode) //public GethStartResult BringOnlineMarketplaceFor(CodexSetup codexSetup)
{ //{
return new GethStartResult(CreateMarketplaceAccessFactory(marketplaceNetwork), marketplaceNetwork, companionNode); // if (codexSetup.MarketplaceConfig == null) return CreateMarketplaceUnavailableResult();
// var marketplaceNetwork = marketplaceNetworkCache.Get();
// var companionNode = StartCompanionNode(codexSetup, marketplaceNetwork);
// LogStart("Setting up initial balance...");
// TransferInitialBalance(marketplaceNetwork, codexSetup.MarketplaceConfig, companionNode);
// LogEnd($"Initial balance of {codexSetup.MarketplaceConfig.InitialTestTokens} set for {codexSetup.NumberOfNodes} nodes.");
// return CreateGethStartResult(marketplaceNetwork, companionNode);
//}
//private void TransferInitialBalance(MarketplaceNetwork marketplaceNetwork, MarketplaceInitialConfig marketplaceConfig, GethCompanionNodeInfo companionNode)
//{
// if (marketplaceConfig.InitialTestTokens.Amount == 0) return;
// var interaction = marketplaceNetwork.StartInteraction(lifecycle);
// var tokenAddress = marketplaceNetwork.Marketplace.TokenAddress;
// var accounts = companionNode.Accounts.Select(a => a.Account).ToArray();
// interaction.MintTestTokens(accounts, marketplaceConfig.InitialTestTokens.Amount, tokenAddress);
//}
//private GethStartResult CreateGethStartResult(MarketplaceNetwork marketplaceNetwork, GethCompanionNodeInfo companionNode)
//{
// return new GethStartResult(CreateMarketplaceAccessFactory(marketplaceNetwork), marketplaceNetwork, companionNode);
//}
//private GethStartResult CreateMarketplaceUnavailableResult()
//{
// return new GethStartResult(new MarketplaceUnavailableAccessFactory(), null!, null!);
//}
//private IMarketplaceAccessFactory CreateMarketplaceAccessFactory(MarketplaceNetwork marketplaceNetwork)
//{
// return new GethMarketplaceAccessFactory(lifecycle, marketplaceNetwork);
//}
//private GethCompanionNodeInfo StartCompanionNode(CodexSetup codexSetup, MarketplaceNetwork marketplaceNetwork)
//{
// return companionNodeStarter.StartCompanionNodeFor(codexSetup, marketplaceNetwork);
//}
} }
private GethStartResult CreateMarketplaceUnavailableResult() //public class MarketplaceNetworkCache
{ //{
return new GethStartResult(new MarketplaceUnavailableAccessFactory(), null!, null!); // private readonly GethBootstrapNodeStarter bootstrapNodeStarter;
} // private readonly CodexContractsStarter codexContractsStarter;
// private MarketplaceNetwork? network;
private IMarketplaceAccessFactory CreateMarketplaceAccessFactory(MarketplaceNetwork marketplaceNetwork) // public MarketplaceNetworkCache(GethBootstrapNodeStarter bootstrapNodeStarter, CodexContractsStarter codexContractsStarter)
{ // {
return new GethMarketplaceAccessFactory(lifecycle, marketplaceNetwork); // this.bootstrapNodeStarter = bootstrapNodeStarter;
} // this.codexContractsStarter = codexContractsStarter;
// }
private GethCompanionNodeInfo StartCompanionNode(CodexSetup codexSetup, MarketplaceNetwork marketplaceNetwork) // public MarketplaceNetwork Get()
{ // {
return companionNodeStarter.StartCompanionNodeFor(codexSetup, marketplaceNetwork); // if (network == null)
} // {
} // var bootstrapInfo = bootstrapNodeStarter.StartGethBootstrapNode();
// var marketplaceInfo = codexContractsStarter.Start(bootstrapInfo);
public class MarketplaceNetworkCache // network = new MarketplaceNetwork(bootstrapInfo, marketplaceInfo);
{ // }
private readonly GethBootstrapNodeStarter bootstrapNodeStarter; // return network;
private readonly CodexContractsStarter codexContractsStarter; // }
private MarketplaceNetwork? network; //}
public MarketplaceNetworkCache(GethBootstrapNodeStarter bootstrapNodeStarter, CodexContractsStarter codexContractsStarter)
{
this.bootstrapNodeStarter = bootstrapNodeStarter;
this.codexContractsStarter = codexContractsStarter;
}
public MarketplaceNetwork Get()
{
if (network == null)
{
var bootstrapInfo = bootstrapNodeStarter.StartGethBootstrapNode();
var marketplaceInfo = codexContractsStarter.Start(bootstrapInfo);
network = new MarketplaceNetwork(bootstrapInfo, marketplaceInfo);
}
return network;
}
}
} }

View File

@ -1,18 +1,48 @@
namespace GethPlugin namespace GethPlugin
{ {
public class GethStartupConfig public interface IGethSetup
{ {
public GethStartupConfig(bool isBootstrapNode, GethBootstrapNodeInfo bootstrapNode, int companionAccountStartIndex, int numberOfCompanionAccounts) IGethSetup IsMiner();
{ IGethSetup WithBootstrapNode(GethBootstrapNode node);
IsBootstrapNode = isBootstrapNode; IGethSetup WithName(string name);
BootstrapNode = bootstrapNode;
CompanionAccountStartIndex = companionAccountStartIndex;
NumberOfCompanionAccounts = numberOfCompanionAccounts;
} }
public bool IsBootstrapNode { get; } public class GethStartupConfig : IGethSetup
public GethBootstrapNodeInfo BootstrapNode { get; } {
public int CompanionAccountStartIndex { get; } public bool IsMiner { get; private set; }
public int NumberOfCompanionAccounts { get; } public GethBootstrapNode? BootstrapNode { get; private set; }
public string? NameOverride { get; private set; }
public IGethSetup WithBootstrapNode(GethBootstrapNode node)
{
BootstrapNode = node;
return this;
}
public IGethSetup WithName(string name)
{
NameOverride = name;
return this;
}
IGethSetup IGethSetup.IsMiner()
{
IsMiner = true;
return this;
}
}
public class GethBootstrapNode
{
public GethBootstrapNode(string publicKey, string ipAddress, int port)
{
PublicKey = publicKey;
IpAddress = ipAddress;
Port = port;
}
public string PublicKey { get; }
public string IpAddress { get; }
public int Port { get; }
} }
} }

View File

@ -51,16 +51,12 @@ namespace KubernetesWorkflow
protected Port AddExposedPort(string tag = "") protected Port AddExposedPort(string tag = "")
{ {
var p = factory.CreatePort(tag); return AddExposedPort(factory.CreatePort(tag));
exposedPorts.Add(p);
return p;
} }
protected Port AddExposedPort(int number, string tag = "") protected Port AddExposedPort(int number, string tag = "")
{ {
var p = factory.CreatePort(number, tag); return AddExposedPort(factory.CreatePort(number, tag));
exposedPorts.Add(p);
return p;
} }
protected Port AddInternalPort(string tag = "") protected Port AddInternalPort(string tag = "")
@ -112,5 +108,16 @@ namespace KubernetesWorkflow
{ {
additionals.Add(userData); additionals.Add(userData);
} }
private Port AddExposedPort(Port port)
{
if (exposedPorts.Any())
{
throw new NotImplementedException("Current implementation only support 1 exposed port per container recipe. " +
$"Methods for determining container addresses in {nameof(StartupWorkflow)} currently rely on this constraint.");
}
exposedPorts.Add(port);
return port;
}
} }
} }

View File

@ -1,5 +1,6 @@
using CodexPlugin; using CodexPlugin;
using DistTestCore; using DistTestCore;
using GethPlugin;
using MetricsPlugin; using MetricsPlugin;
using NUnit.Framework; using NUnit.Framework;
using Utils; using Utils;
@ -46,6 +47,8 @@ namespace Tests.BasicTests
[Test] [Test]
public void MarketplaceExample() public void MarketplaceExample()
{ {
var geth = Ci.StartGethNode(s => s.IsMiner().WithName("disttest-geth"));
//var sellerInitialBalance = 234.TestTokens(); //var sellerInitialBalance = 234.TestTokens();
//var buyerInitialBalance = 1000.TestTokens(); //var buyerInitialBalance = 1000.TestTokens();
//var fileSize = 10.MB(); //var fileSize = 10.MB();

View File

@ -15,6 +15,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\CodexPlugin\CodexPlugin.csproj" /> <ProjectReference Include="..\CodexPlugin\CodexPlugin.csproj" />
<ProjectReference Include="..\DistTestCore\DistTestCore.csproj" /> <ProjectReference Include="..\DistTestCore\DistTestCore.csproj" />
<ProjectReference Include="..\GethPlugin\GethPlugin.csproj" />
<ProjectReference Include="..\MetricsPlugin\MetricsPlugin.csproj" /> <ProjectReference Include="..\MetricsPlugin\MetricsPlugin.csproj" />
</ItemGroup> </ItemGroup>