Setting up geth plugin

This commit is contained in:
ThatBen 2023-09-15 12:36:35 +02:00
parent f7c69d6f24
commit f2a8c123a5
22 changed files with 500 additions and 396 deletions

View File

@ -14,6 +14,7 @@
<ProjectReference Include="..\Core\Core.csproj" /> <ProjectReference Include="..\Core\Core.csproj" />
<ProjectReference Include="..\KubernetesWorkflow\KubernetesWorkflow.csproj" /> <ProjectReference Include="..\KubernetesWorkflow\KubernetesWorkflow.csproj" />
<ProjectReference Include="..\MetricsPlugin\MetricsPlugin.csproj" /> <ProjectReference Include="..\MetricsPlugin\MetricsPlugin.csproj" />
<ProjectReference Include="..\Nethereum\NethereumWorkflow.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,88 +0,0 @@
//using DistTestCore.Marketplace;
//namespace CodexPlugin
//{
// public class GethStarter : BaseStarter
// {
// private readonly MarketplaceNetworkCache marketplaceNetworkCache;
// private readonly GethCompanionNodeStarter companionNodeStarter;
// public GethStarter(TestLifecycle lifecycle)
// : base(lifecycle)
// {
// marketplaceNetworkCache = new MarketplaceNetworkCache(
// new GethBootstrapNodeStarter(lifecycle),
// new CodexContractsStarter(lifecycle));
// companionNodeStarter = new GethCompanionNodeStarter(lifecycle);
// }
// public GethStartResult BringOnlineMarketplaceFor(CodexSetup codexSetup)
// {
// 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);
// }
// }
// public class MarketplaceNetworkCache
// {
// private readonly GethBootstrapNodeStarter bootstrapNodeStarter;
// 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,42 +0,0 @@
//using KubernetesWorkflow;
//using NethereumWorkflow;
//namespace DistTestCore.Marketplace
//{
// 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,40 +0,0 @@
//using KubernetesWorkflow;
//namespace DistTestCore.Marketplace
//{
// public class GethBootstrapNodeStarter : BaseStarter
// {
// public GethBootstrapNodeStarter(TestLifecycle lifecycle)
// : base(lifecycle)
// {
// }
// 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 +0,0 @@
//using KubernetesWorkflow;
//using NethereumWorkflow;
//namespace DistTestCore.Marketplace
//{
// public class GethCompanionNodeInfo
// {
// public GethCompanionNodeInfo(RunningContainer runningContainer, GethAccount[] accounts)
// {
// RunningContainer = runningContainer;
// Accounts = accounts;
// }
// public RunningContainer RunningContainer { get; }
// public GethAccount[] Accounts { get; }
// public NethereumInteraction StartInteraction(TestLifecycle lifecycle, GethAccount account)
// {
// var address = lifecycle.Configuration.GetAddress(RunningContainer);
// var privateKey = account.PrivateKey;
// var creator = new NethereumInteractionCreator(lifecycle.Log, address.Host, address.Port, privateKey);
// 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,77 +0,0 @@
//using KubernetesWorkflow;
//using Utils;
//namespace DistTestCore.Marketplace
//{
// public class GethCompanionNodeStarter : BaseStarter
// {
// private int companionAccountIndex = 0;
// public GethCompanionNodeStarter(TestLifecycle lifecycle)
// : base(lifecycle)
// {
// }
// 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

@ -1,73 +0,0 @@
//using KubernetesWorkflow;
//namespace DistTestCore.Marketplace
//{
// public class GethContainerRecipe : DefaultContainerRecipe
// {
// private const string defaultArgs = "--ipcdisable --syncmode full";
// public const string HttpPortTag = "http_port";
// public const string DiscoveryPortTag = "disc_port";
// public const string AccountsFilename = "accounts.csv";
// public override string AppName => "geth";
// public override string Image => "codexstorage/dist-tests-geth:latest";
// protected override void InitializeRecipe(StartupConfig startupConfig)
// {
// var config = startupConfig.Get<GethStartupConfig>();
// var args = CreateArgs(config);
// AddEnvVar("GETH_ARGS", args);
// }
// private string CreateArgs(GethStartupConfig config)
// {
// var discovery = AddInternalPort(tag: DiscoveryPortTag);
// if (config.IsBootstrapNode)
// {
// return CreateBootstapArgs(discovery);
// }
// return CreateCompanionArgs(discovery, config);
// }
// private string CreateBootstapArgs(Port discovery)
// {
// AddEnvVar("ENABLE_MINER", "1");
// UnlockAccounts(0, 1);
// var exposedPort = AddExposedPort(tag: HttpPortTag);
// return $"--http.port {exposedPort.Number} --port {discovery.Number} --discovery.port {discovery.Number} {defaultArgs}";
// }
// private string CreateCompanionArgs(Port discovery, GethStartupConfig config)
// {
// 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)
// {
// if (startIndex < 0) throw new ArgumentException();
// if (numberOfAccounts < 1) throw new ArgumentException();
// if (startIndex + numberOfAccounts > 1000) throw new ArgumentException("Out of accounts!");
// AddEnvVar("UNLOCK_START_INDEX", startIndex.ToString());
// AddEnvVar("UNLOCK_NUMBER", numberOfAccounts.ToString());
// }
// }
//}

View File

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

View File

@ -1,18 +0,0 @@
//namespace DistTestCore.Marketplace
//{
// public class GethStartupConfig
// {
// public GethStartupConfig(bool isBootstrapNode, GethBootstrapNodeInfo bootstrapNode, int companionAccountStartIndex, int numberOfCompanionAccounts)
// {
// IsBootstrapNode = isBootstrapNode;
// BootstrapNode = bootstrapNode;
// CompanionAccountStartIndex = companionAccountStartIndex;
// NumberOfCompanionAccounts = numberOfCompanionAccounts;
// }
// public bool IsBootstrapNode { get; }
// public GethBootstrapNodeInfo BootstrapNode { get; }
// public int CompanionAccountStartIndex { get; }
// public int NumberOfCompanionAccounts { get; }
// }
//}

View File

@ -31,6 +31,11 @@ namespace Core
return logHandler.DownloadLog(); return logHandler.DownloadLog();
} }
public string ExecuteContainerCommand(IHasContainer containerSource, string command, params string[] args)
{
return ExecuteContainerCommand(containerSource.Container, command, args);
}
public string ExecuteContainerCommand(RunningContainer container, string command, params string[] args) public string ExecuteContainerCommand(RunningContainer container, string command, params string[] args)
{ {
var workflow = entryPoint.Tools.CreateWorkflow(); var workflow = entryPoint.Tools.CreateWorkflow();

View File

@ -0,0 +1,44 @@
using Core;
using KubernetesWorkflow;
namespace GethPlugin
{
public static class CoreInterfaceExtensions
{
//public static RunningContainers[] StartCodexNodes(this CoreInterface ci, int number, Action<ICodexSetup> setup)
//{
// return Plugin(ci).StartCodexNodes(number, setup);
//}
//public static ICodexNodeGroup WrapCodexContainers(this CoreInterface ci, RunningContainers[] containers)
//{
// return Plugin(ci).WrapCodexContainers(containers);
//}
//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>();
//}
}
}

View File

@ -0,0 +1,42 @@
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

@ -0,0 +1,35 @@
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

@ -0,0 +1,38 @@
using KubernetesWorkflow;
using NethereumWorkflow;
namespace GethPlugin
{
public class GethCompanionNodeInfo
{
public GethCompanionNodeInfo(RunningContainer runningContainer, GethAccount[] accounts)
{
RunningContainer = runningContainer;
Accounts = accounts;
}
public RunningContainer RunningContainer { get; }
public GethAccount[] Accounts { get; }
public NethereumInteraction StartInteraction(TestLifecycle lifecycle, GethAccount account)
{
var address = lifecycle.Configuration.GetAddress(RunningContainer);
var privateKey = account.PrivateKey;
var creator = new NethereumInteractionCreator(lifecycle.Log, address.Host, address.Port, privateKey);
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

@ -0,0 +1,72 @@
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

@ -0,0 +1,73 @@
using KubernetesWorkflow;
namespace GethPlugin
{
public class GethContainerRecipe : ContainerRecipeFactory
{
private const string defaultArgs = "--ipcdisable --syncmode full";
public const string HttpPortTag = "http_port";
public const string DiscoveryPortTag = "disc_port";
public const string AccountsFilename = "accounts.csv";
public override string AppName => "geth";
public override string Image => "codexstorage/dist-tests-geth:latest";
protected override void Initialize(StartupConfig startupConfig)
{
var config = startupConfig.Get<GethStartupConfig>();
var args = CreateArgs(config);
AddEnvVar("GETH_ARGS", args);
}
private string CreateArgs(GethStartupConfig config)
{
var discovery = AddInternalPort(tag: DiscoveryPortTag);
if (config.IsBootstrapNode)
{
return CreateBootstapArgs(discovery);
}
return CreateCompanionArgs(discovery, config);
}
private string CreateBootstapArgs(Port discovery)
{
AddEnvVar("ENABLE_MINER", "1");
UnlockAccounts(0, 1);
var exposedPort = AddExposedPort(tag: HttpPortTag);
return $"--http.port {exposedPort.Number} --port {discovery.Number} --discovery.port {discovery.Number} {defaultArgs}";
}
private string CreateCompanionArgs(Port discovery, GethStartupConfig config)
{
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)
{
if (startIndex < 0) throw new ArgumentException();
if (numberOfAccounts < 1) throw new ArgumentException();
if (startIndex + numberOfAccounts > 1000) throw new ArgumentException("Out of accounts!");
AddEnvVar("UNLOCK_START_INDEX", startIndex.ToString());
AddEnvVar("UNLOCK_NUMBER", numberOfAccounts.ToString());
}
}
}

45
GethPlugin/GethPlugin.cs Normal file
View File

@ -0,0 +1,45 @@
using Core;
using KubernetesWorkflow;
namespace GethPlugin
{
public class GethPlugin : IProjectPlugin, IHasLogPrefix, IHasMetadata
{
private readonly IPluginTools tools;
public GethPlugin(IPluginTools tools)
{
//codexStarter = new CodexStarter(tools);
this.tools = tools;
}
public string LogPrefix => "(Geth) ";
public void Announce()
{
//tools.GetLog().Log($"Loaded with Codex ID: '{codexStarter.GetCodexId()}'");
}
public void AddMetadata(IAddMetadata metadata)
{
//metadata.Add("codexid", codexStarter.GetCodexId());
}
public void Decommission()
{
}
//public RunningContainers[] StartCodexNodes(int numberOfNodes, Action<ICodexSetup> setup)
//{
// var codexSetup = new CodexSetup(numberOfNodes);
// codexSetup.LogLevel = defaultLogLevel;
// setup(codexSetup);
// return codexStarter.BringOnline(codexSetup);
//}
//public ICodexNodeGroup WrapCodexContainers(RunningContainers[] containers)
//{
// return codexStarter.WrapCodexContainers(containers);
//}
}
}

View File

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Core\Core.csproj" />
<ProjectReference Include="..\KubernetesWorkflow\KubernetesWorkflow.csproj" />
<ProjectReference Include="..\Nethereum\NethereumWorkflow.csproj" />
</ItemGroup>
</Project>

View File

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

86
GethPlugin/GethStarter.cs Normal file
View File

@ -0,0 +1,86 @@
namespace CodexPlugin
{
public class GethStarter
{
private readonly MarketplaceNetworkCache marketplaceNetworkCache;
private readonly GethCompanionNodeStarter companionNodeStarter;
public GethStarter(TestLifecycle lifecycle)
: base(lifecycle)
{
marketplaceNetworkCache = new MarketplaceNetworkCache(
new GethBootstrapNodeStarter(lifecycle),
new CodexContractsStarter(lifecycle));
companionNodeStarter = new GethCompanionNodeStarter(lifecycle);
}
public GethStartResult BringOnlineMarketplaceFor(CodexSetup codexSetup)
{
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);
}
}
public class MarketplaceNetworkCache
{
private readonly GethBootstrapNodeStarter bootstrapNodeStarter;
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

@ -0,0 +1,18 @@
namespace GethPlugin
{
public class GethStartupConfig
{
public GethStartupConfig(bool isBootstrapNode, GethBootstrapNodeInfo bootstrapNode, int companionAccountStartIndex, int numberOfCompanionAccounts)
{
IsBootstrapNode = isBootstrapNode;
BootstrapNode = bootstrapNode;
CompanionAccountStartIndex = companionAccountStartIndex;
NumberOfCompanionAccounts = numberOfCompanionAccounts;
}
public bool IsBootstrapNode { get; }
public GethBootstrapNodeInfo BootstrapNode { get; }
public int CompanionAccountStartIndex { get; }
public int NumberOfCompanionAccounts { get; }
}
}

View File

@ -29,7 +29,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CodexPlugin", "CodexPlugin\
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core", "Core\Core.csproj", "{F2BF34B3-C660-43EF-BD42-BC5C60237FC4}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core", "Core\Core.csproj", "{F2BF34B3-C660-43EF-BD42-BC5C60237FC4}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MetricsPlugin", "MetricsPlugin\MetricsPlugin.csproj", "{FCC74AF1-463D-4E5A-9FE7-B4A13F7C8820}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MetricsPlugin", "MetricsPlugin\MetricsPlugin.csproj", "{FCC74AF1-463D-4E5A-9FE7-B4A13F7C8820}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GethPlugin", "GethPlugin\GethPlugin.csproj", "{5A1EF1DD-9E81-4501-B44C-493C72D2B166}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -93,6 +95,10 @@ Global
{FCC74AF1-463D-4E5A-9FE7-B4A13F7C8820}.Debug|Any CPU.Build.0 = Debug|Any CPU {FCC74AF1-463D-4E5A-9FE7-B4A13F7C8820}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FCC74AF1-463D-4E5A-9FE7-B4A13F7C8820}.Release|Any CPU.ActiveCfg = Release|Any CPU {FCC74AF1-463D-4E5A-9FE7-B4A13F7C8820}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FCC74AF1-463D-4E5A-9FE7-B4A13F7C8820}.Release|Any CPU.Build.0 = Release|Any CPU {FCC74AF1-463D-4E5A-9FE7-B4A13F7C8820}.Release|Any CPU.Build.0 = Release|Any CPU
{5A1EF1DD-9E81-4501-B44C-493C72D2B166}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5A1EF1DD-9E81-4501-B44C-493C72D2B166}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5A1EF1DD-9E81-4501-B44C-493C72D2B166}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5A1EF1DD-9E81-4501-B44C-493C72D2B166}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE