Can send eth

This commit is contained in:
benbierens 2023-09-19 11:51:59 +02:00
parent a20fc6864b
commit 58b1c1e03c
No known key found for this signature in database
GPG Key ID: FE44815D96D0A1AA
31 changed files with 289 additions and 175 deletions

View File

@ -14,8 +14,8 @@ namespace CodexContractsPlugin
{ {
var config = startupConfig.Get<CodexContractsContainerConfig>(); var config = startupConfig.Get<CodexContractsContainerConfig>();
var ip = config.GethNode.RunningContainer.Pod.PodInfo.Ip; var ip = config.GethNode.StartResult.RunningContainer.Pod.PodInfo.Ip;
var port = config.GethNode.HttpPort.Number; var port = config.GethNode.StartResult.HttpPort.Number;
AddEnvVar("DISTTEST_NETWORK_URL", $"http://{ip}:{port}"); AddEnvVar("DISTTEST_NETWORK_URL", $"http://{ip}:{port}");
AddEnvVar("HARDHAT_NETWORK", "codexdisttestnetwork"); AddEnvVar("HARDHAT_NETWORK", "codexdisttestnetwork");

View File

@ -38,7 +38,7 @@ namespace CodexContractsPlugin
var marketplaceAddress = extractor.ExtractMarketplaceAddress(); var marketplaceAddress = extractor.ExtractMarketplaceAddress();
var abi = extractor.ExtractMarketplaceAbi(); var abi = extractor.ExtractMarketplaceAbi();
var interaction = gethNode.StartInteraction(tools.GetLog()); var interaction = gethNode.StartInteraction();
var tokenAddress = interaction.GetTokenAddress(marketplaceAddress); var tokenAddress = interaction.GetTokenAddress(marketplaceAddress);
Log("Extract completed. Marketplace deployed."); Log("Extract completed. Marketplace deployed.");

View File

@ -0,0 +1,45 @@
namespace CodexContractsPlugin
{
public class TestToken : IComparable<TestToken>
{
public TestToken(decimal amount)
{
Amount = amount;
}
public decimal Amount { get; }
public int CompareTo(TestToken? other)
{
return Amount.CompareTo(other!.Amount);
}
public override bool Equals(object? obj)
{
return obj is TestToken token && Amount == token.Amount;
}
public override int GetHashCode()
{
return HashCode.Combine(Amount);
}
public override string ToString()
{
return $"{Amount} TestTokens";
}
}
public static class TokensIntExtensions
{
public static TestToken TestTokens(this int i)
{
return TestTokens(Convert.ToDecimal(i));
}
public static TestToken TestTokens(this decimal i)
{
return new TestToken(i);
}
}
}

View File

@ -80,8 +80,9 @@ namespace CodexPlugin
if (config.MarketplaceConfig != null) if (config.MarketplaceConfig != null)
{ {
var mconfig = config.MarketplaceConfig; var mconfig = config.MarketplaceConfig;
var ip = mconfig.GethNode.RunningContainer.Pod.PodInfo.Ip; var gethStart = mconfig.GethNode.StartResult;
var port = mconfig.GethNode.WsPort.Number; var ip = gethStart.RunningContainer.Pod.PodInfo.Ip;
var port = gethStart.WsPort.Number;
var marketplaceAddress = mconfig.CodexContracts.MarketplaceAddress; var marketplaceAddress = mconfig.CodexContracts.MarketplaceAddress;
AddEnvVar("CODEX_ETH_PROVIDER", $"ws://{ip}:{port}"); AddEnvVar("CODEX_ETH_PROVIDER", $"ws://{ip}:{port}");

View File

@ -1,5 +1,6 @@
using Core; using Core;
using FileUtils; using FileUtils;
using GethPlugin;
using KubernetesWorkflow; using KubernetesWorkflow;
using Logging; using Logging;
using MetricsPlugin; using MetricsPlugin;
@ -8,28 +9,29 @@ using Utils;
namespace CodexPlugin namespace CodexPlugin
{ {
public interface IOnlineCodexNode : IHasContainer public interface ICodexNode : IHasContainer, IHasMetricsScrapeTarget, IHasEthAddress
{ {
string GetName(); string GetName();
CodexDebugResponse GetDebugInfo(); CodexDebugResponse GetDebugInfo();
CodexDebugPeerResponse GetDebugPeer(string peerId); CodexDebugPeerResponse GetDebugPeer(string peerId);
ContentId UploadFile(TrackedFile file); ContentId UploadFile(TrackedFile file);
TrackedFile? DownloadContent(ContentId contentId, string fileLabel = ""); TrackedFile? DownloadContent(ContentId contentId, string fileLabel = "");
void ConnectToPeer(IOnlineCodexNode node); void ConnectToPeer(ICodexNode node);
CodexDebugVersionResponse Version { get; } CodexDebugVersionResponse Version { get; }
void BringOffline(); void Stop();
IMetricsScrapeTarget MetricsScrapeTarget { get; }
} }
public class OnlineCodexNode : IOnlineCodexNode public class CodexNode : ICodexNode
{ {
private const string SuccessfullyConnectedMessage = "Successfully connected to peer"; private const string SuccessfullyConnectedMessage = "Successfully connected to peer";
private const string UploadFailedMessage = "Unable to store block"; private const string UploadFailedMessage = "Unable to store block";
private readonly IPluginTools tools; private readonly IPluginTools tools;
private readonly IEthAddress? ethAddress;
public OnlineCodexNode(IPluginTools tools, CodexAccess codexAccess, CodexNodeGroup group) public CodexNode(IPluginTools tools, CodexAccess codexAccess, CodexNodeGroup group, IEthAddress? ethAddress)
{ {
this.tools = tools; this.tools = tools;
this.ethAddress = ethAddress;
CodexAccess = codexAccess; CodexAccess = codexAccess;
Group = group; Group = group;
Version = new CodexDebugVersionResponse(); Version = new CodexDebugVersionResponse();
@ -48,6 +50,14 @@ namespace CodexPlugin
return new MetricsScrapeTarget(CodexAccess.Container, port); return new MetricsScrapeTarget(CodexAccess.Container, port);
} }
} }
public IEthAddress EthAddress
{
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;
}
}
public string GetName() public string GetName()
{ {
@ -95,9 +105,9 @@ namespace CodexPlugin
return file; return file;
} }
public void ConnectToPeer(IOnlineCodexNode node) public void ConnectToPeer(ICodexNode node)
{ {
var peer = (OnlineCodexNode)node; var peer = (CodexNode)node;
Log($"Connecting to peer {peer.GetName()}..."); Log($"Connecting to peer {peer.GetName()}...");
var peerInfo = node.GetDebugInfo(); var peerInfo = node.GetDebugInfo();
@ -107,7 +117,7 @@ namespace CodexPlugin
Log($"Successfully connected to peer {peer.GetName()}."); Log($"Successfully connected to peer {peer.GetName()}.");
} }
public void BringOffline() public void Stop()
{ {
if (Group.Count() > 1) throw new InvalidOperationException("Codex-nodes that are part of a group cannot be " + if (Group.Count() > 1) throw new InvalidOperationException("Codex-nodes that are part of a group cannot be " +
"individually shut down. Use 'BringOffline()' on the group object to stop the group. This method is only " + "individually shut down. Use 'BringOffline()' on the group object to stop the group. This method is only " +
@ -132,7 +142,7 @@ namespace CodexPlugin
Version = debugInfo.codex; Version = debugInfo.codex;
} }
private string GetPeerMultiAddress(OnlineCodexNode peer, CodexDebugResponse peerInfo) private string GetPeerMultiAddress(CodexNode peer, CodexDebugResponse peerInfo)
{ {
var multiAddress = peerInfo.addrs.First(); var multiAddress = peerInfo.addrs.First();
// Todo: Is there a case where First address in list is not the way? // Todo: Is there a case where First address in list is not the way?

View File

@ -1,10 +1,11 @@
using Core; using Core;
using GethPlugin;
namespace CodexPlugin namespace CodexPlugin
{ {
public interface ICodexNodeFactory public interface ICodexNodeFactory
{ {
OnlineCodexNode CreateOnlineCodexNode(CodexAccess access, CodexNodeGroup group); CodexNode CreateOnlineCodexNode(CodexAccess access, CodexNodeGroup group);
} }
public class CodexNodeFactory : ICodexNodeFactory public class CodexNodeFactory : ICodexNodeFactory
@ -27,11 +28,21 @@ namespace CodexPlugin
// this.marketplaceAccessFactory = marketplaceAccessFactory; // this.marketplaceAccessFactory = marketplaceAccessFactory;
//} //}
public OnlineCodexNode CreateOnlineCodexNode(CodexAccess access, CodexNodeGroup group) public CodexNode CreateOnlineCodexNode(CodexAccess access, CodexNodeGroup group)
{ {
var ethAddress = GetEthAddress(access);
//var metricsAccess = metricsAccessFactory.CreateMetricsAccess(access.Container); //var metricsAccess = metricsAccessFactory.CreateMetricsAccess(access.Container);
//var marketplaceAccess = marketplaceAccessFactory.CreateMarketplaceAccess(access); //var marketplaceAccess = marketplaceAccessFactory.CreateMarketplaceAccess(access);
return new OnlineCodexNode(tools, access, group/*, metricsAccess, marketplaceAccess*/); return new CodexNode(tools, access, group, ethAddress);
}
private IEthAddress? GetEthAddress(CodexAccess access)
{
var mStart = access.Container.Recipe.Additionals.SingleOrDefault(a => a is MarketplaceStartResults) as MarketplaceStartResults;
if (mStart == null) return null;
return mStart.EthAddress;
} }
} }
} }

View File

@ -5,10 +5,10 @@ using System.Collections;
namespace CodexPlugin namespace CodexPlugin
{ {
public interface ICodexNodeGroup : IEnumerable<IOnlineCodexNode>, IManyMetricScrapeTargets public interface ICodexNodeGroup : IEnumerable<ICodexNode>, IHasManyMetricScrapeTargets
{ {
void BringOffline(); void BringOffline();
IOnlineCodexNode this[int index] { get; } ICodexNode this[int index] { get; }
} }
public class CodexNodeGroup : ICodexNodeGroup public class CodexNodeGroup : ICodexNodeGroup
@ -23,7 +23,7 @@ namespace CodexPlugin
Version = new CodexDebugVersionResponse(); Version = new CodexDebugVersionResponse();
} }
public IOnlineCodexNode this[int index] public ICodexNode this[int index]
{ {
get get
{ {
@ -35,18 +35,18 @@ namespace CodexPlugin
{ {
starter.BringOffline(this); starter.BringOffline(this);
// Clear everything. Prevent accidental use. // Clear everything. Prevent accidental use.
Nodes = Array.Empty<OnlineCodexNode>(); Nodes = Array.Empty<CodexNode>();
Containers = null!; Containers = null!;
} }
public RunningContainers[] Containers { get; private set; } public RunningContainers[] Containers { get; private set; }
public OnlineCodexNode[] Nodes { get; private set; } public CodexNode[] Nodes { get; private set; }
public CodexDebugVersionResponse Version { get; private set; } public CodexDebugVersionResponse Version { get; private set; }
public IMetricsScrapeTarget[] ScrapeTargets => Nodes.Select(n => n.MetricsScrapeTarget).ToArray(); public IMetricsScrapeTarget[] ScrapeTargets => Nodes.Select(n => n.MetricsScrapeTarget).ToArray();
public IEnumerator<IOnlineCodexNode> GetEnumerator() public IEnumerator<ICodexNode> GetEnumerator()
{ {
return Nodes.Cast<IOnlineCodexNode>().GetEnumerator(); return Nodes.Cast<ICodexNode>().GetEnumerator();
} }
IEnumerator IEnumerable.GetEnumerator() IEnumerator IEnumerable.GetEnumerator()
@ -74,7 +74,7 @@ namespace CodexPlugin
Version = first; Version = first;
} }
private OnlineCodexNode CreateOnlineCodexNode(RunningContainer c, IPluginTools tools, ICodexNodeFactory factory) private CodexNode CreateOnlineCodexNode(RunningContainer c, IPluginTools tools, ICodexNodeFactory factory)
{ {
var access = new CodexAccess(tools, c); var access = new CodexAccess(tools, c);
return factory.CreateOnlineCodexNode(access, this); return factory.CreateOnlineCodexNode(access, this);

View File

@ -10,7 +10,7 @@ namespace CodexPlugin
ICodexSetup WithLogLevel(CodexLogLevel logLevel); ICodexSetup WithLogLevel(CodexLogLevel logLevel);
ICodexSetup WithName(string name); ICodexSetup WithName(string name);
ICodexSetup At(Location location); ICodexSetup At(Location location);
ICodexSetup WithBootstrapNode(IOnlineCodexNode node); ICodexSetup WithBootstrapNode(ICodexNode node);
ICodexSetup WithStorageQuota(ByteSize storageQuota); ICodexSetup WithStorageQuota(ByteSize storageQuota);
ICodexSetup WithBlockTTL(TimeSpan duration); ICodexSetup WithBlockTTL(TimeSpan duration);
ICodexSetup WithBlockMaintenanceInterval(TimeSpan duration); ICodexSetup WithBlockMaintenanceInterval(TimeSpan duration);
@ -50,7 +50,7 @@ namespace CodexPlugin
return this; return this;
} }
public ICodexSetup WithBootstrapNode(IOnlineCodexNode node) public ICodexSetup WithBootstrapNode(ICodexNode node)
{ {
BootstrapSpr = node.GetDebugInfo().spr; BootstrapSpr = node.GetDebugInfo().spr;
return this; return this;

View File

@ -15,12 +15,12 @@ namespace CodexPlugin
return Plugin(ci).WrapCodexContainers(containers); return Plugin(ci).WrapCodexContainers(containers);
} }
public static IOnlineCodexNode SetupCodexNode(this CoreInterface ci) public static ICodexNode SetupCodexNode(this CoreInterface ci)
{ {
return ci.SetupCodexNodes(1)[0]; return ci.SetupCodexNodes(1)[0];
} }
public static IOnlineCodexNode SetupCodexNode(this CoreInterface ci, Action<ICodexSetup> setup) public static ICodexNode SetupCodexNode(this CoreInterface ci, Action<ICodexSetup> setup)
{ {
return ci.SetupCodexNodes(1, setup)[0]; return ci.SetupCodexNodes(1, setup)[0];
} }

View File

@ -1,15 +1,17 @@
namespace CodexPlugin using GethPlugin;
namespace CodexPlugin
{ {
[Serializable] [Serializable]
public class MarketplaceStartResults public class MarketplaceStartResults
{ {
public MarketplaceStartResults(string ethAddress, string privateKey) public MarketplaceStartResults(IEthAddress ethAddress, string privateKey)
{ {
EthAddress = ethAddress; EthAddress = ethAddress;
PrivateKey = privateKey; PrivateKey = privateKey;
} }
public string EthAddress { get; } public IEthAddress EthAddress { get; }
public string PrivateKey { get; } public string PrivateKey { get; }
} }
} }

View File

@ -1,4 +1,5 @@
using Nethereum.Hex.HexConvertors.Extensions; using GethPlugin;
using Nethereum.Hex.HexConvertors.Extensions;
using Nethereum.Web3.Accounts; using Nethereum.Web3.Accounts;
namespace CodexPlugin namespace CodexPlugin
@ -10,8 +11,9 @@ namespace CodexPlugin
var ecKey = Nethereum.Signer.EthECKey.GenerateKey(); var ecKey = Nethereum.Signer.EthECKey.GenerateKey();
var privateKey = ecKey.GetPrivateKeyAsBytes().ToHex(); var privateKey = ecKey.GetPrivateKeyAsBytes().ToHex();
var account = new Account(privateKey); var account = new Account(privateKey);
var ethAddress = new EthAddress(account.Address);
return new MarketplaceStartResults(account.Address, account.PrivateKey); return new MarketplaceStartResults(ethAddress, account.PrivateKey);
} }
} }
} }

View File

@ -6,7 +6,8 @@ namespace GethPlugin
{ {
public static IGethNode StartGethNode(this CoreInterface ci, Action<IGethSetup> setup) public static IGethNode StartGethNode(this CoreInterface ci, Action<IGethSetup> setup)
{ {
return Plugin(ci).StartGeth(setup); var p = Plugin(ci);
return p.WrapGethContainer(p.StartGeth(setup));
} }
private static GethPlugin Plugin(CoreInterface ci) private static GethPlugin Plugin(CoreInterface ci)

22
GethPlugin/EthAddress.cs Normal file
View File

@ -0,0 +1,22 @@
namespace GethPlugin
{
public interface IEthAddress
{
string Address { get; }
}
public interface IHasEthAddress
{
IEthAddress EthAddress { get; }
}
public class EthAddress : IEthAddress
{
public EthAddress(string address)
{
Address = address;
}
public string Address { get; }
}
}

View File

@ -1,13 +1,15 @@
namespace DistTestCore namespace GethPlugin
{ {
public class Ether : IComparable<Ether> public class Ether : IComparable<Ether>
{ {
public Ether(decimal wei) public Ether(decimal wei)
{ {
Wei = wei; Wei = wei;
Eth = wei / TokensIntExtensions.WeiPerEth;
} }
public decimal Wei { get; } public decimal Wei { get; }
public decimal Eth { get; }
public int CompareTo(Ether? other) public int CompareTo(Ether? other)
{ {
@ -30,49 +32,9 @@
} }
} }
public class TestToken : IComparable<TestToken>
{
public TestToken(decimal amount)
{
Amount = amount;
}
public decimal Amount { get; }
public int CompareTo(TestToken? other)
{
return Amount.CompareTo(other!.Amount);
}
public override bool Equals(object? obj)
{
return obj is TestToken token && Amount == token.Amount;
}
public override int GetHashCode()
{
return HashCode.Combine(Amount);
}
public override string ToString()
{
return $"{Amount} TestTokens";
}
}
public static class TokensIntExtensions public static class TokensIntExtensions
{ {
private const decimal weiPerEth = 1000000000000000000; public const decimal WeiPerEth = 1000000000000000000;
public static TestToken TestTokens(this int i)
{
return TestTokens(Convert.ToDecimal(i));
}
public static TestToken TestTokens(this decimal i)
{
return new TestToken(i);
}
public static Ether Eth(this int i) public static Ether Eth(this int i)
{ {
@ -86,7 +48,7 @@
public static Ether Eth(this decimal i) public static Ether Eth(this decimal i)
{ {
return new Ether(i * weiPerEth); return new Ether(i * WeiPerEth);
} }
public static Ether Wei(this decimal i) public static Ether Wei(this decimal i)

View File

@ -1,47 +1,67 @@
using KubernetesWorkflow; using Logging;
using Logging;
using NethereumWorkflow; using NethereumWorkflow;
namespace GethPlugin namespace GethPlugin
{ {
public interface IGethNode public interface IGethNode
{ {
RunningContainer RunningContainer { get; } IGethStartResult StartResult { get; }
Port DiscoveryPort { get; }
Port HttpPort { get; }
Port WsPort { get; }
NethereumInteraction StartInteraction(ILog log); NethereumInteraction StartInteraction();
Ether GetEthBalance();
Ether GetEthBalance(IHasEthAddress address);
Ether GetEthBalance(IEthAddress address);
void SendEth(IHasEthAddress account, Ether eth);
void SendEth(IEthAddress account, Ether eth);
} }
public class GethNode : IGethNode public class GethNode : IGethNode
{ {
public GethNode(RunningContainer runningContainer, AllGethAccounts allAccounts, string pubKey, Port discoveryPort, Port httpPort, Port wsPort) private readonly ILog log;
public GethNode(ILog log, IGethStartResult startResult)
{ {
RunningContainer = runningContainer; this.log = log;
AllAccounts = allAccounts; StartResult = startResult;
Account = allAccounts.Accounts[0]; Account = startResult.AllAccounts.Accounts.First();
PubKey = pubKey;
DiscoveryPort = discoveryPort;
HttpPort = httpPort;
WsPort = wsPort;
} }
public RunningContainer RunningContainer { get; } public IGethStartResult StartResult { get; }
public AllGethAccounts AllAccounts { get; }
public GethAccount Account { get; } public GethAccount Account { get; }
public string PubKey { get; }
public Port DiscoveryPort { get; }
public Port HttpPort { get; }
public Port WsPort { get; }
public NethereumInteraction StartInteraction(ILog log) public NethereumInteraction StartInteraction()
{ {
var address = RunningContainer.Address; var address = StartResult.RunningContainer.Address;
var account = Account; var account = Account;
var creator = new NethereumInteractionCreator(log, address.Host, address.Port, account.PrivateKey); var creator = new NethereumInteractionCreator(log, address.Host, address.Port, account.PrivateKey);
return creator.CreateWorkflow(); return creator.CreateWorkflow();
} }
public Ether GetEthBalance()
{
return StartInteraction().GetEthBalance().Eth();
}
public Ether GetEthBalance(IHasEthAddress owner)
{
return GetEthBalance(owner.EthAddress);
}
public Ether GetEthBalance(IEthAddress address)
{
return StartInteraction().GetEthBalance(address.Address).Eth();
}
public void SendEth(IHasEthAddress owner, Ether eth)
{
SendEth(owner.EthAddress, eth);
}
public void SendEth(IEthAddress account, Ether eth)
{
var i = StartInteraction();
i.SendEth(account.Address, eth.Eth);
}
} }
} }

View File

@ -1,16 +1,13 @@
using Core; using Core;
using KubernetesWorkflow;
namespace GethPlugin namespace GethPlugin
{ {
public class GethPlugin : IProjectPlugin, IHasLogPrefix, IHasMetadata public class GethPlugin : IProjectPlugin, IHasLogPrefix, IHasMetadata
{ {
private readonly IPluginTools tools;
private readonly GethStarter starter; private readonly GethStarter starter;
public GethPlugin(IPluginTools tools) public GethPlugin(IPluginTools tools)
{ {
this.tools = tools;
starter = new GethStarter(tools); starter = new GethStarter(tools);
} }
@ -30,24 +27,16 @@ namespace GethPlugin
{ {
} }
public IGethNode StartGeth(Action<IGethSetup> setup) public IGethStartResult StartGeth(Action<IGethSetup> setup)
{ {
var startupConfig = new GethStartupConfig(); var startupConfig = new GethStartupConfig();
setup(startupConfig); setup(startupConfig);
return starter.StartGeth(startupConfig); return starter.StartGeth(startupConfig);
} }
//public RunningContainers[] StartCodexNodes(int numberOfNodes, Action<ICodexSetup> setup) public IGethNode WrapGethContainer(IGethStartResult startResult)
//{ {
// var codexSetup = new CodexSetup(numberOfNodes); return starter.WrapGethContainer(startResult);
// codexSetup.LogLevel = defaultLogLevel; }
// setup(codexSetup);
// return codexStarter.BringOnline(codexSetup);
//}
//public ICodexNodeGroup WrapCodexContainers(RunningContainers[] containers)
//{
// return codexStarter.WrapCodexContainers(containers);
//}
} }
} }

View File

@ -1,19 +1,34 @@
//using Newtonsoft.Json; using KubernetesWorkflow;
//namespace GethPlugin namespace GethPlugin
//{ {
// public class GethStartResult public interface IGethStartResult
// { {
// public GethStartResult(IMarketplaceAccessFactory marketplaceAccessFactory, MarketplaceNetwork marketplaceNetwork, GethCompanionNodeInfo companionNode) RunningContainer RunningContainer { get; }
// { Port DiscoveryPort { get; }
// MarketplaceAccessFactory = marketplaceAccessFactory; Port HttpPort { get; }
// MarketplaceNetwork = marketplaceNetwork; Port WsPort { get; }
// CompanionNode = companionNode; AllGethAccounts AllAccounts { get; }
// } string PubKey { get; }
}
// [JsonIgnore] public class GethStartResult : IGethStartResult
// public IMarketplaceAccessFactory MarketplaceAccessFactory { get; } {
// public MarketplaceNetwork MarketplaceNetwork { get; } public GethStartResult(RunningContainer runningContainer, Port discoveryPort, Port httpPort, Port wsPort, AllGethAccounts allAccounts, string pubKey)
// public GethCompanionNodeInfo CompanionNode { get; } {
// } RunningContainer = runningContainer;
//} DiscoveryPort = discoveryPort;
HttpPort = httpPort;
WsPort = wsPort;
AllAccounts = allAccounts;
PubKey = pubKey;
}
public RunningContainer RunningContainer { get; }
public Port DiscoveryPort { get; }
public Port HttpPort { get; }
public Port WsPort { get; }
public AllGethAccounts AllAccounts { get; }
public string PubKey { get; }
}
}

View File

@ -12,7 +12,7 @@ namespace GethPlugin
this.tools = tools; this.tools = tools;
} }
public IGethNode StartGeth(GethStartupConfig gethStartupConfig) public IGethStartResult StartGeth(GethStartupConfig gethStartupConfig)
{ {
Log("Starting Geth bootstrap node..."); Log("Starting Geth bootstrap node...");
@ -28,7 +28,7 @@ namespace GethPlugin
var extractor = new GethContainerInfoExtractor(tools.GetLog(), workflow, container); var extractor = new GethContainerInfoExtractor(tools.GetLog(), workflow, container);
var accounts = extractor.ExtractAccounts(); var accounts = extractor.ExtractAccounts();
var pubKey = extractor.ExtractPubKey(); var pubKey = extractor.ExtractPubKey();
var discoveryPort = container.Recipe.GetPortByTag(GethContainerRecipe.DiscoveryPortTag); var discoveryPort = container.Recipe.GetPortByTag(GethContainerRecipe.DiscoveryPortTag);
if (discoveryPort == null) throw new Exception("Expected discovery port to be created."); if (discoveryPort == null) throw new Exception("Expected discovery port to be created.");
var httpPort = container.Recipe.GetPortByTag(GethContainerRecipe.HttpPortTag); var httpPort = container.Recipe.GetPortByTag(GethContainerRecipe.HttpPortTag);
@ -36,11 +36,14 @@ namespace GethPlugin
var wsPort = container.Recipe.GetPortByTag(GethContainerRecipe.wsPortTag); var wsPort = container.Recipe.GetPortByTag(GethContainerRecipe.wsPortTag);
if (wsPort == null) throw new Exception("Expected ws port to be created."); if (wsPort == null) throw new Exception("Expected ws port to be created.");
var result = new GethNode(container, accounts, pubKey, discoveryPort, httpPort, wsPort); Log($"Geth node started.");
Log($"Geth bootstrap node started with account '{result.Account.Account}'"); return new GethStartResult(container, discoveryPort, httpPort, wsPort, accounts, pubKey);
}
return result; public IGethNode WrapGethContainer(IGethStartResult startResult)
{
return new GethNode(tools.GetLog(), startResult);
} }
private void Log(string msg) private void Log(string msg)

View File

@ -6,6 +6,11 @@ namespace MetricsPlugin
{ {
public static class CoreInterfaceExtensions public static class CoreInterfaceExtensions
{ {
public static RunningContainer StartMetricsCollector(this CoreInterface ci, params IHasMetricsScrapeTarget[] scrapeTargets)
{
return Plugin(ci).StartMetricsCollector(scrapeTargets.Select(t => t.MetricsScrapeTarget).ToArray());
}
public static RunningContainer StartMetricsCollector(this CoreInterface ci, params IMetricsScrapeTarget[] scrapeTargets) public static RunningContainer StartMetricsCollector(this CoreInterface ci, params IMetricsScrapeTarget[] scrapeTargets)
{ {
return Plugin(ci).StartMetricsCollector(scrapeTargets); return Plugin(ci).StartMetricsCollector(scrapeTargets);
@ -16,11 +21,16 @@ namespace MetricsPlugin
return Plugin(ci).CreateAccessForTarget(metricsContainer, scrapeTarget); return Plugin(ci).CreateAccessForTarget(metricsContainer, scrapeTarget);
} }
public static IMetricsAccess[] GetMetricsFor(this CoreInterface ci, params IManyMetricScrapeTargets[] manyScrapeTargets) public static IMetricsAccess[] GetMetricsFor(this CoreInterface ci, params IHasManyMetricScrapeTargets[] manyScrapeTargets)
{ {
return ci.GetMetricsFor(manyScrapeTargets.SelectMany(t => t.ScrapeTargets).ToArray()); return ci.GetMetricsFor(manyScrapeTargets.SelectMany(t => t.ScrapeTargets).ToArray());
} }
public static IMetricsAccess[] GetMetricsFor(this CoreInterface ci, params IHasMetricsScrapeTarget[] scrapeTargets)
{
return ci.GetMetricsFor(scrapeTargets.Select(t => t.MetricsScrapeTarget).ToArray());
}
public static IMetricsAccess[] GetMetricsFor(this CoreInterface ci, params IMetricsScrapeTarget[] scrapeTargets) public static IMetricsAccess[] GetMetricsFor(this CoreInterface ci, params IMetricsScrapeTarget[] scrapeTargets)
{ {
var rc = ci.StartMetricsCollector(scrapeTargets); var rc = ci.StartMetricsCollector(scrapeTargets);

View File

@ -9,7 +9,12 @@ namespace MetricsPlugin
int Port { get; } int Port { get; }
} }
public interface IManyMetricScrapeTargets public interface IHasMetricsScrapeTarget
{
IMetricsScrapeTarget MetricsScrapeTarget { get; }
}
public interface IHasManyMetricScrapeTargets
{ {
IMetricsScrapeTarget[] ScrapeTargets { get; } IMetricsScrapeTarget[] ScrapeTargets { get; }
} }

View File

@ -2,6 +2,7 @@
using Nethereum.ABI.FunctionEncoding.Attributes; using Nethereum.ABI.FunctionEncoding.Attributes;
using Nethereum.Contracts; using Nethereum.Contracts;
using Nethereum.Hex.HexTypes; using Nethereum.Hex.HexTypes;
using Nethereum.RPC.Eth.DTOs;
using Nethereum.Web3; using Nethereum.Web3;
using System.Numerics; using System.Numerics;
using Utils; using Utils;
@ -19,6 +20,23 @@ namespace NethereumWorkflow
this.web3 = web3; this.web3 = web3;
} }
public void SendEth(string toAddress, decimal ethAmount)
{
var receipt = Time.Wait(web3.Eth.GetEtherTransferService().TransferEtherAndWaitForReceiptAsync(toAddress, ethAmount));
if (!receipt.Succeeded()) throw new Exception("Unable to send Eth");
}
public decimal GetEthBalance()
{
return GetEthBalance(web3.TransactionManager.Account.Address);
}
public decimal GetEthBalance(string address)
{
var balance = Time.Wait(web3.Eth.GetBalance.SendRequestAsync(address));
return Web3.Convert.FromWei(balance.Value);
}
public string GetTokenAddress(string marketplaceAddress) public string GetTokenAddress(string marketplaceAddress)
{ {
log.Debug(marketplaceAddress); log.Debug(marketplaceAddress);

View File

@ -1,13 +1,11 @@
using CodexPlugin; using CodexPlugin;
using DistTestCore;
using DistTestCore.Helpers;
using NUnit.Framework; using NUnit.Framework;
namespace Tests namespace Tests
{ {
public class AutoBootstrapDistTest : CodexDistTest public class AutoBootstrapDistTest : CodexDistTest
{ {
private readonly List<IOnlineCodexNode> onlineCodexNodes = new List<IOnlineCodexNode>(); private readonly List<ICodexNode> onlineCodexNodes = new List<ICodexNode>();
[SetUp] [SetUp]
public void SetUpBootstrapNode() public void SetUpBootstrapNode()
@ -21,6 +19,6 @@ namespace Tests
if (BootstrapNode != null) setup.WithBootstrapNode(BootstrapNode); if (BootstrapNode != null) setup.WithBootstrapNode(BootstrapNode);
} }
protected IOnlineCodexNode? BootstrapNode { get; private set; } protected ICodexNode? BootstrapNode { get; private set; }
} }
} }

View File

@ -21,7 +21,7 @@ namespace Tests.BasicTests
.WithBlockTTL(TimeSpan.FromMinutes(2)) .WithBlockTTL(TimeSpan.FromMinutes(2))
.WithStorageQuota(1.GB())); .WithStorageQuota(1.GB()));
var nodes = group.Cast<OnlineCodexNode>().ToArray(); var nodes = group.Cast<CodexNode>().ToArray();
foreach (var node in nodes) foreach (var node in nodes)
{ {
@ -58,7 +58,7 @@ namespace Tests.BasicTests
.WithBlockTTL(TimeSpan.FromMinutes(2)) .WithBlockTTL(TimeSpan.FromMinutes(2))
.WithStorageQuota(1.GB())); .WithStorageQuota(1.GB()));
var nodes = group.Cast<OnlineCodexNode>().ToArray(); var nodes = group.Cast<CodexNode>().ToArray();
var checkTime = DateTime.UtcNow + TimeSpan.FromMinutes(1); var checkTime = DateTime.UtcNow + TimeSpan.FromMinutes(1);
var endTime = DateTime.UtcNow + TimeSpan.FromHours(10); var endTime = DateTime.UtcNow + TimeSpan.FromHours(10);
@ -75,7 +75,7 @@ namespace Tests.BasicTests
} }
} }
private void CheckRoutingTables(IEnumerable<IOnlineCodexNode> nodes) private void CheckRoutingTables(IEnumerable<ICodexNode> nodes)
{ {
var all = nodes.ToArray(); var all = nodes.ToArray();
var allIds = all.Select(n => n.GetDebugInfo().table.localNode.nodeId).ToArray(); var allIds = all.Select(n => n.GetDebugInfo().table.localNode.nodeId).ToArray();
@ -88,7 +88,7 @@ namespace Tests.BasicTests
} }
} }
private string AreAllPresent(IOnlineCodexNode n, string[] allIds) private string AreAllPresent(ICodexNode n, string[] allIds)
{ {
var info = n.GetDebugInfo(); var info = n.GetDebugInfo();
var known = info.table.nodes.Select(n => n.nodeId).ToArray(); var known = info.table.nodes.Select(n => n.nodeId).ToArray();
@ -104,7 +104,7 @@ namespace Tests.BasicTests
private ByteSize fileSize = 80.MB(); private ByteSize fileSize = 80.MB();
private void PerformTest(IOnlineCodexNode primary, IOnlineCodexNode secondary) private void PerformTest(ICodexNode primary, ICodexNode secondary)
{ {
ScopedTestFiles(() => ScopedTestFiles(() =>
{ {
@ -129,7 +129,7 @@ namespace Tests.BasicTests
.WithBlockMaintenanceNumber(10000) .WithBlockMaintenanceNumber(10000)
.WithStorageQuota(2000.MB())); .WithStorageQuota(2000.MB()));
var nodes = group.Cast<OnlineCodexNode>().ToArray(); var nodes = group.Cast<CodexNode>().ToArray();
var endTime = DateTime.UtcNow + TimeSpan.FromHours(24); var endTime = DateTime.UtcNow + TimeSpan.FromHours(24);

View File

@ -34,7 +34,7 @@ namespace Tests.BasicTests
var primary2 = group2[0]; var primary2 = group2[0];
var secondary2 = group2[1]; var secondary2 = group2[1];
var metrics = Ci.GetMetricsFor(primary.MetricsScrapeTarget, primary2.MetricsScrapeTarget); var metrics = Ci.GetMetricsFor(primary, primary2);
primary.ConnectToPeer(secondary); primary.ConnectToPeer(secondary);
primary2.ConnectToPeer(secondary2); primary2.ConnectToPeer(secondary2);
@ -54,9 +54,9 @@ namespace Tests.BasicTests
var node = Ci.SetupCodexNode(s => s.EnableMarketplace(geth, contracts)); var node = Ci.SetupCodexNode(s => s.EnableMarketplace(geth, contracts));
var i = 0; var myBalance = geth.GetEthBalance();
geth.SendEth(node, 10.Eth());
//geth.SendEth(node.EthAddress, 10.Eth()); var nodeBalance = geth.GetEthBalance(node);
//contracts.MintTestTokens(geth, node.EthAddress, 100.TestTokens()); //contracts.MintTestTokens(geth, node.EthAddress, 100.TestTokens());
@ -64,7 +64,7 @@ namespace Tests.BasicTests
//contracts.GetTestTokenBalance(geth, node.EthAddress); //contracts.GetTestTokenBalance(geth, node.EthAddress);
var i = 0;
//var sellerInitialBalance = 234.TestTokens(); //var sellerInitialBalance = 234.TestTokens();

View File

@ -12,7 +12,7 @@ namespace Tests.BasicTests
[Ignore("Disabled until a solution is implemented.")] [Ignore("Disabled until a solution is implemented.")]
public class NetworkIsolationTest : DistTest public class NetworkIsolationTest : DistTest
{ {
private IOnlineCodexNode? node = null; private ICodexNode? node = null;
[Test] [Test]
public void SetUpANodeAndWait() public void SetUpANodeAndWait()

View File

@ -21,14 +21,14 @@ namespace Tests.BasicTests
{ {
var primary = Ci.SetupCodexNode(); var primary = Ci.SetupCodexNode();
primary.BringOffline(); primary.Stop();
primary = Ci.SetupCodexNode(); primary = Ci.SetupCodexNode();
PerformOneClientTest(primary); PerformOneClientTest(primary);
} }
private void PerformOneClientTest(IOnlineCodexNode primary) private void PerformOneClientTest(ICodexNode primary)
{ {
var testFile = GenerateTestFile(1.MB()); var testFile = GenerateTestFile(1.MB());

View File

@ -29,12 +29,12 @@ namespace Tests.BasicTests
PerformTwoClientTest(primary, secondary); PerformTwoClientTest(primary, secondary);
} }
private void PerformTwoClientTest(IOnlineCodexNode primary, IOnlineCodexNode secondary) private void PerformTwoClientTest(ICodexNode primary, ICodexNode secondary)
{ {
PerformTwoClientTest(primary, secondary, 1.MB()); PerformTwoClientTest(primary, secondary, 1.MB());
} }
private void PerformTwoClientTest(IOnlineCodexNode primary, IOnlineCodexNode secondary, ByteSize size) private void PerformTwoClientTest(ICodexNode primary, ICodexNode secondary, ByteSize size)
{ {
primary.ConnectToPeer(secondary); primary.ConnectToPeer(secondary);

View File

@ -6,14 +6,14 @@ namespace Tests
{ {
public class CodexDistTest : DistTest public class CodexDistTest : DistTest
{ {
private readonly List<IOnlineCodexNode> onlineCodexNodes = new List<IOnlineCodexNode>(); private readonly List<ICodexNode> onlineCodexNodes = new List<ICodexNode>();
public IOnlineCodexNode AddCodex() public ICodexNode AddCodex()
{ {
return AddCodex(s => { }); return AddCodex(s => { });
} }
public IOnlineCodexNode AddCodex(Action<ICodexSetup> setup) public ICodexNode AddCodex(Action<ICodexSetup> setup)
{ {
return AddCodex(1, setup)[0]; return AddCodex(1, setup)[0];
} }
@ -44,7 +44,7 @@ namespace Tests
return new PeerDownloadTestHelpers(GetTestLog(), Get().GetFileManager()); return new PeerDownloadTestHelpers(GetTestLog(), Get().GetFileManager());
} }
public IEnumerable<IOnlineCodexNode> GetAllOnlineCodexNodes() public IEnumerable<ICodexNode> GetAllOnlineCodexNodes()
{ {
return onlineCodexNodes; return onlineCodexNodes;
} }

View File

@ -23,12 +23,12 @@ namespace DistTestCore.Helpers
this.implementation = implementation; this.implementation = implementation;
} }
public void AssertFullyConnected(IEnumerable<IOnlineCodexNode> nodes) public void AssertFullyConnected(IEnumerable<ICodexNode> nodes)
{ {
AssertFullyConnected(nodes.ToArray()); AssertFullyConnected(nodes.ToArray());
} }
private void AssertFullyConnected(IOnlineCodexNode[] nodes) private void AssertFullyConnected(ICodexNode[] nodes)
{ {
Log($"Asserting '{implementation.Description()}' for nodes: '{string.Join(",", nodes.Select(n => n.GetName()))}'..."); Log($"Asserting '{implementation.Description()}' for nodes: '{string.Join(",", nodes.Select(n => n.GetName()))}'...");
var entries = CreateEntries(nodes); var entries = CreateEntries(nodes);
@ -67,7 +67,7 @@ namespace DistTestCore.Helpers
Log($"Connections successful:{Nl}{string.Join(Nl, results)}"); Log($"Connections successful:{Nl}{string.Join(Nl, results)}");
} }
private Entry[] CreateEntries(IOnlineCodexNode[] nodes) private Entry[] CreateEntries(ICodexNode[] nodes)
{ {
var entries = nodes.Select(n => new Entry(n)).ToArray(); var entries = nodes.Select(n => new Entry(n)).ToArray();
@ -107,13 +107,13 @@ namespace DistTestCore.Helpers
public class Entry public class Entry
{ {
public Entry(IOnlineCodexNode node) public Entry(ICodexNode node)
{ {
Node = node; Node = node;
Response = node.GetDebugInfo(); Response = node.GetDebugInfo();
} }
public IOnlineCodexNode Node { get; } public ICodexNode Node { get; }
public CodexDebugResponse Response { get; } public CodexDebugResponse Response { get; }
public override string ToString() public override string ToString()

View File

@ -13,7 +13,7 @@ namespace DistTestCore.Helpers
helper = new FullConnectivityHelper(log, this); helper = new FullConnectivityHelper(log, this);
} }
public void AssertFullyConnected(IEnumerable<IOnlineCodexNode> nodes) public void AssertFullyConnected(IEnumerable<ICodexNode> nodes)
{ {
helper.AssertFullyConnected(nodes); helper.AssertFullyConnected(nodes);
} }

View File

@ -21,7 +21,7 @@ namespace DistTestCore.Helpers
this.fileManager = fileManager; this.fileManager = fileManager;
} }
public void AssertFullDownloadInterconnectivity(IEnumerable<IOnlineCodexNode> nodes, ByteSize testFileSize) public void AssertFullDownloadInterconnectivity(IEnumerable<ICodexNode> nodes, ByteSize testFileSize)
{ {
this.testFileSize = testFileSize; this.testFileSize = testFileSize;
helper.AssertFullyConnected(nodes); helper.AssertFullyConnected(nodes);
@ -62,12 +62,12 @@ namespace DistTestCore.Helpers
// Should an exception occur during upload, then this try is inconclusive and we try again next loop. // Should an exception occur during upload, then this try is inconclusive and we try again next loop.
} }
private TrackedFile? DownloadFile(IOnlineCodexNode node, ContentId contentId, string label) private TrackedFile? DownloadFile(ICodexNode node, ContentId contentId, string label)
{ {
return node.DownloadContent(contentId, label); return node.DownloadContent(contentId, label);
} }
private TrackedFile GenerateTestFile(IOnlineCodexNode uploader, IOnlineCodexNode downloader) private TrackedFile GenerateTestFile(ICodexNode uploader, ICodexNode downloader)
{ {
var up = uploader.GetName().Replace("<", "").Replace(">", ""); var up = uploader.GetName().Replace("<", "").Replace(">", "");
var down = downloader.GetName().Replace("<", "").Replace(">", ""); var down = downloader.GetName().Replace("<", "").Replace(">", "");