Setting up access to marketplace address

This commit is contained in:
benbierens 2023-04-18 10:22:11 +02:00
parent f06216b931
commit 9b38447dbe
No known key found for this signature in database
GPG Key ID: FE44815D96D0A1AA
18 changed files with 192 additions and 66 deletions

View File

@ -10,7 +10,7 @@
public long SizeInBytes { get; }
}
public static class IntExtensions
public static class ByteSizeIntExtensions
{
private const long Kilo = 1024;

View File

@ -11,7 +11,8 @@ namespace DistTestCore
//ICodexStartupConfig WithBootstrapNode(IOnlineCodexNode node);
ICodexSetup WithStorageQuota(ByteSize storageQuota);
ICodexSetup EnableMetrics();
ICodexSetup EnableMarketplace(int initialBalance);
ICodexSetup EnableMarketplace(TestToken initialBalance);
ICodexSetup EnableMarketplace(TestToken initialBalance, Ether initialEther);
ICodexNodeGroup BringOnline();
}
@ -62,9 +63,14 @@ namespace DistTestCore
return this;
}
public ICodexSetup EnableMarketplace(int initialBalance)
public ICodexSetup EnableMarketplace(TestToken initialBalance)
{
MarketplaceConfig = new MarketplaceInitialConfig(initialBalance);
return EnableMarketplace(initialBalance, 1000.Eth());
}
public ICodexSetup EnableMarketplace(TestToken initialBalance, Ether initialEther)
{
MarketplaceConfig = new MarketplaceInitialConfig(initialEther, initialBalance);
return this;
}

View File

@ -8,6 +8,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="nunit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.4.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />

View File

@ -5,13 +5,15 @@ namespace DistTestCore
{
public class GethStarter
{
private readonly GethBootstrapNodeCache bootstrapNodeCache;
private readonly MarketplaceNetworkCache marketplaceNetworkCache;
private readonly GethCompanionNodeStarter companionNodeStarter;
private readonly TestLifecycle lifecycle;
public GethStarter(TestLifecycle lifecycle, WorkflowCreator workflowCreator)
{
bootstrapNodeCache = new GethBootstrapNodeCache(new GethBootstrapNodeStarter(lifecycle, workflowCreator));
marketplaceNetworkCache = new MarketplaceNetworkCache(
new GethBootstrapNodeStarter(lifecycle, workflowCreator),
new CodexContractsStarter(lifecycle, workflowCreator));
companionNodeStarter = new GethCompanionNodeStarter(lifecycle, workflowCreator);
this.lifecycle = lifecycle;
}
@ -20,26 +22,28 @@ namespace DistTestCore
{
if (codexSetup.MarketplaceConfig == null) return CreateMarketplaceUnavailableResult();
var bootstrapNode = bootstrapNodeCache.Get();
var companionNodes = StartCompanionNodes(codexSetup, bootstrapNode);
var marketplaceNetwork = marketplaceNetworkCache.Get();
var companionNodes = StartCompanionNodes(codexSetup, marketplaceNetwork);
TransferInitialBalance(bootstrapNode, codexSetup.MarketplaceConfig.InitialBalance, companionNodes);
TransferInitialBalance(marketplaceNetwork, codexSetup.MarketplaceConfig, companionNodes);
return CreateGethStartResult(bootstrapNode, companionNodes);
return CreateGethStartResult(marketplaceNetwork, companionNodes);
}
private void TransferInitialBalance(GethBootstrapNodeInfo bootstrapNode, int initialBalance, GethCompanionNodeInfo[] companionNodes)
private void TransferInitialBalance(MarketplaceNetwork marketplaceNetwork, MarketplaceInitialConfig marketplaceConfig, GethCompanionNodeInfo[] companionNodes)
{
var interaction = bootstrapNode.StartInteraction(lifecycle.Log);
var interaction = marketplaceNetwork.StartInteraction(lifecycle.Log);
foreach (var node in companionNodes)
{
interaction.TransferTo(node.Account, initialBalance);
interaction.TransferTo(node.Account, marketplaceConfig.InitialEth.Wei);
// wrong level: mintTestTokens? interactions knows nothing about contract details!
//interaction.MintTestTokens(node.Account, marketplaceConfig.InitialTestTokens.Amount);
}
}
private GethStartResult CreateGethStartResult(GethBootstrapNodeInfo bootstrapNode, GethCompanionNodeInfo[] companionNodes)
private GethStartResult CreateGethStartResult(MarketplaceNetwork marketplaceNetwork, GethCompanionNodeInfo[] companionNodes)
{
return new GethStartResult(CreateMarketplaceAccessFactory(bootstrapNode), bootstrapNode, companionNodes);
return new GethStartResult(CreateMarketplaceAccessFactory(marketplaceNetwork), marketplaceNetwork, companionNodes);
}
private GethStartResult CreateMarketplaceUnavailableResult()
@ -47,34 +51,38 @@ namespace DistTestCore
return new GethStartResult(new MarketplaceUnavailableAccessFactory(), null!, Array.Empty<GethCompanionNodeInfo>());
}
private IMarketplaceAccessFactory CreateMarketplaceAccessFactory(GethBootstrapNodeInfo bootstrapNode)
private IMarketplaceAccessFactory CreateMarketplaceAccessFactory(MarketplaceNetwork marketplaceNetwork)
{
return new GethMarketplaceAccessFactory(lifecycle.Log, bootstrapNode!);
return new GethMarketplaceAccessFactory(lifecycle.Log, marketplaceNetwork);
}
private GethCompanionNodeInfo[] StartCompanionNodes(CodexSetup codexSetup, GethBootstrapNodeInfo bootstrapNode)
private GethCompanionNodeInfo[] StartCompanionNodes(CodexSetup codexSetup, MarketplaceNetwork marketplaceNetwork)
{
return companionNodeStarter.StartCompanionNodesFor(codexSetup, bootstrapNode);
return companionNodeStarter.StartCompanionNodesFor(codexSetup, marketplaceNetwork.Bootstrap);
}
}
public class GethBootstrapNodeCache
public class MarketplaceNetworkCache
{
private readonly GethBootstrapNodeStarter bootstrapNodeStarter;
private GethBootstrapNodeInfo? bootstrapNode;
private readonly CodexContractsStarter codexContractsStarter;
private MarketplaceNetwork? network;
public GethBootstrapNodeCache(GethBootstrapNodeStarter bootstrapNodeStarter)
public MarketplaceNetworkCache(GethBootstrapNodeStarter bootstrapNodeStarter, CodexContractsStarter codexContractsStarter)
{
this.bootstrapNodeStarter = bootstrapNodeStarter;
this.codexContractsStarter = codexContractsStarter;
}
public GethBootstrapNodeInfo Get()
public MarketplaceNetwork Get()
{
if (bootstrapNode == null)
if (network == null)
{
bootstrapNode = bootstrapNodeStarter.StartGethBootstrapNode();
var bootstrapInfo = bootstrapNodeStarter.StartGethBootstrapNode();
var marketplaceInfo = codexContractsStarter.Start(bootstrapInfo.RunningContainers.Containers[0]);
network = new MarketplaceNetwork(bootstrapInfo, marketplaceInfo );
}
return bootstrapNode;
return network;
}
}
}

View File

@ -5,6 +5,7 @@ namespace DistTestCore.Marketplace
public class CodexContractsContainerRecipe : ContainerRecipeFactory
{
public const string DockerImage = "thatbenbierens/codex-contracts-deployment";
public const string MarketplaceAddressFilename = "/usr/app/deployments/codexdisttestnetwork/Marketplace.json";
protected override string Image => DockerImage;

View File

@ -15,7 +15,7 @@ namespace DistTestCore.Marketplace
this.workflowCreator = workflowCreator;
}
public void Start(RunningContainer bootstrapContainer)
public MarketplaceInfo Start(RunningContainer bootstrapContainer)
{
var workflow = workflowCreator.CreateWorkflow();
var startupConfig = CreateStartupConfig(bootstrapContainer);
@ -32,7 +32,12 @@ namespace DistTestCore.Marketplace
return logHandler.Found;
});
var extractor = new ContainerInfoExtractor(workflow, container);
var marketplaceAddress = extractor.ExtractMarketplaceAddress();
lifecycle.Log.Log("Contracts deployed.");
return new MarketplaceInfo(marketplaceAddress);
}
private void WaitUntil(Func<bool> predicate)
@ -49,6 +54,16 @@ namespace DistTestCore.Marketplace
}
}
public class MarketplaceInfo
{
public MarketplaceInfo(string address)
{
Address = address;
}
public string Address { get; }
}
public class ContractsReadyLogHandler : LogHandler
{
private readonly string targetString;

View File

@ -1,14 +1,15 @@
using KubernetesWorkflow;
using Newtonsoft.Json;
using System.Text;
namespace DistTestCore.Marketplace
{
public class GethInfoExtractor
public class ContainerInfoExtractor
{
private readonly StartupWorkflow workflow;
private readonly RunningContainer container;
public GethInfoExtractor(StartupWorkflow workflow, RunningContainer container)
public ContainerInfoExtractor(StartupWorkflow workflow, RunningContainer container)
{
this.workflow = workflow;
this.container = container;
@ -38,6 +39,14 @@ namespace DistTestCore.Marketplace
return pubKey;
}
public string ExtractMarketplaceAddress()
{
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;
}
private string Retry(Func<string> fetch)
{
var result = Catch(fetch);
@ -71,6 +80,13 @@ namespace DistTestCore.Marketplace
return workflow.ExecuteCommand(container, "cat", GethContainerRecipe.AccountFilename);
}
private string FetchMarketplaceAddress()
{
var json = workflow.ExecuteCommand(container, "cat", CodexContractsContainerRecipe.MarketplaceAddressFilename);
var marketplace = JsonConvert.DeserializeObject<MarketplaceJson>(json);
return marketplace!.address;
}
private string FetchPubKey()
{
var enodeFinder = new PubKeyFinder();
@ -107,4 +123,9 @@ namespace DistTestCore.Marketplace
length: closeIndex - openIndex);
}
}
public class MarketplaceJson
{
public string address { get; set; } = string.Empty;
}
}

View File

@ -1,6 +1,4 @@
using KubernetesWorkflow;
using Logging;
using NethereumWorkflow;
namespace DistTestCore.Marketplace
{
@ -20,14 +18,5 @@ namespace DistTestCore.Marketplace
public string GenesisJsonBase64 { get; }
public string PubKey { get; }
public Port DiscoveryPort { get; }
public NethereumInteraction StartInteraction(TestLog log)
{
var ip = RunningContainers.RunningPod.Cluster.IP;
var port = RunningContainers.Containers[0].ServicePorts[0].Number;
var creator = new NethereumInteractionCreator(log, ip, port, Account);
return creator.CreateWorkflow();
}
}
}

View File

@ -7,13 +7,11 @@ namespace DistTestCore.Marketplace
private const string bootstrapGenesisJsonBase64 = "ewogICAgImNvbmZpZyI6IHsKICAgICAgImNoYWluSWQiOiA3ODk5ODgsCiAgICAgICJob21lc3RlYWRCbG9jayI6IDAsCiAgICAgICJlaXAxNTBCbG9jayI6IDAsCiAgICAgICJlaXAxNTVCbG9jayI6IDAsCiAgICAgICJlaXAxNThCbG9jayI6IDAsCiAgICAgICJieXphbnRpdW1CbG9jayI6IDAsCiAgICAgICJjb25zdGFudGlub3BsZUJsb2NrIjogMCwKICAgICAgInBldGVyc2J1cmdCbG9jayI6IDAsCiAgICAgICJpc3RhbmJ1bEJsb2NrIjogMCwKICAgICAgIm11aXJHbGFjaWVyQmxvY2siOiAwLAogICAgICAiYmVybGluQmxvY2siOiAwLAogICAgICAibG9uZG9uQmxvY2siOiAwLAogICAgICAiYXJyb3dHbGFjaWVyQmxvY2siOiAwLAogICAgICAiZ3JheUdsYWNpZXJCbG9jayI6IDAsCiAgICAgICJjbGlxdWUiOiB7CiAgICAgICAgInBlcmlvZCI6IDUsCiAgICAgICAgImVwb2NoIjogMzAwMDAKICAgICAgfQogICAgfSwKICAgICJkaWZmaWN1bHR5IjogIjEiLAogICAgImdhc0xpbWl0IjogIjgwMDAwMDAwMCIsCiAgICAiZXh0cmFkYXRhIjogIjB4MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMEFDQ09VTlRfSEVSRTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAiLAogICAgImFsbG9jIjogewogICAgICAiMHhBQ0NPVU5UX0hFUkUiOiB7ICJiYWxhbmNlIjogIjUwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAiIH0KICAgIH0KICB9";
private readonly TestLifecycle lifecycle;
private readonly WorkflowCreator workflowCreator;
private readonly CodexContractsStarter codexContractsStarter;
public GethBootstrapNodeStarter(TestLifecycle lifecycle, WorkflowCreator workflowCreator)
{
this.lifecycle = lifecycle;
this.workflowCreator = workflowCreator;
codexContractsStarter = new CodexContractsStarter(lifecycle, workflowCreator);
}
public GethBootstrapNodeInfo StartGethBootstrapNode()
@ -26,7 +24,7 @@ namespace DistTestCore.Marketplace
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 GethInfoExtractor(workflow, bootstrapContainer);
var extractor = new ContainerInfoExtractor(workflow, bootstrapContainer);
var account = extractor.ExtractAccount();
var genesisJsonBase64 = extractor.ExtractGenesisJsonBase64();
var pubKey = extractor.ExtractPubKey();
@ -34,16 +32,9 @@ namespace DistTestCore.Marketplace
Log($"Geth bootstrap node started with account '{account}'");
DeployCodexContracts(bootstrapContainer);
return new GethBootstrapNodeInfo(containers, account, genesisJsonBase64, pubKey, discoveryPort);
}
private void DeployCodexContracts(RunningContainer bootstrapContainer)
{
codexContractsStarter.Start(bootstrapContainer);
}
private StartupConfig CreateBootstrapStartupConfig()
{
var config = new StartupConfig();

View File

@ -30,7 +30,7 @@ namespace DistTestCore.Marketplace
private GethCompanionNodeInfo CreateCompanionInfo(StartupWorkflow workflow, RunningContainer container)
{
var extractor = new GethInfoExtractor(workflow, container);
var extractor = new ContainerInfoExtractor(workflow, container);
var account = extractor.ExtractAccount();
return new GethCompanionNodeInfo(container, account);
}

View File

@ -2,15 +2,15 @@
{
public class GethStartResult
{
public GethStartResult(IMarketplaceAccessFactory marketplaceAccessFactory, GethBootstrapNodeInfo bootstrapNode, GethCompanionNodeInfo[] companionNodes)
public GethStartResult(IMarketplaceAccessFactory marketplaceAccessFactory, MarketplaceNetwork marketplaceNetwork, GethCompanionNodeInfo[] companionNodes)
{
MarketplaceAccessFactory = marketplaceAccessFactory;
BootstrapNode = bootstrapNode;
MarketplaceNetwork = marketplaceNetwork;
CompanionNodes = companionNodes;
}
public IMarketplaceAccessFactory MarketplaceAccessFactory { get; }
public GethBootstrapNodeInfo BootstrapNode { get; }
public MarketplaceNetwork MarketplaceNetwork { get; }
public GethCompanionNodeInfo[] CompanionNodes { get; }
}
}

View File

@ -15,13 +15,13 @@ namespace DistTestCore.Marketplace
public class MarketplaceAccess : IMarketplaceAccess
{
private readonly TestLog log;
private readonly GethBootstrapNodeInfo bootstrapNode;
private readonly MarketplaceNetwork marketplaceNetwork;
private readonly GethCompanionNodeInfo companionNode;
public MarketplaceAccess(TestLog log, GethBootstrapNodeInfo bootstrapNode, GethCompanionNodeInfo companionNode)
public MarketplaceAccess(TestLog log, MarketplaceNetwork marketplaceNetwork, GethCompanionNodeInfo companionNode)
{
this.log = log;
this.bootstrapNode = bootstrapNode;
this.marketplaceNetwork = marketplaceNetwork;
this.companionNode = companionNode;
}
@ -42,7 +42,7 @@ namespace DistTestCore.Marketplace
public decimal GetBalance()
{
var interaction = bootstrapNode.StartInteraction(log);
var interaction = marketplaceNetwork.StartInteraction(log);
return interaction.GetBalance(companionNode.Account);
}
}

View File

@ -19,18 +19,18 @@ namespace DistTestCore.Marketplace
public class GethMarketplaceAccessFactory : IMarketplaceAccessFactory
{
private readonly TestLog log;
private readonly GethBootstrapNodeInfo bootstrapNode;
private readonly MarketplaceNetwork marketplaceNetwork;
public GethMarketplaceAccessFactory(TestLog log, GethBootstrapNodeInfo bootstrapNode)
public GethMarketplaceAccessFactory(TestLog log, MarketplaceNetwork marketplaceNetwork)
{
this.log = log;
this.bootstrapNode = bootstrapNode;
this.marketplaceNetwork = marketplaceNetwork;
}
public IMarketplaceAccess CreateMarketplaceAccess(CodexAccess access)
{
var companionNode = GetGethCompanionNode(access);
return new MarketplaceAccess(log, bootstrapNode, companionNode);
return new MarketplaceAccess(log, marketplaceNetwork, companionNode);
}
private GethCompanionNodeInfo GetGethCompanionNode(CodexAccess access)

View File

@ -2,11 +2,13 @@
{
public class MarketplaceInitialConfig
{
public MarketplaceInitialConfig(int initialBalance)
public MarketplaceInitialConfig(Ether initialEth, TestToken initialTestTokens)
{
InitialBalance = initialBalance;
InitialEth = initialEth;
InitialTestTokens = initialTestTokens;
}
public int InitialBalance { get; }
public Ether InitialEth { get; }
public TestToken InitialTestTokens { get; }
}
}

View File

@ -0,0 +1,27 @@
using Logging;
using NethereumWorkflow;
namespace DistTestCore.Marketplace
{
public class MarketplaceNetwork
{
public MarketplaceNetwork(GethBootstrapNodeInfo bootstrap, MarketplaceInfo marketplace)
{
Bootstrap = bootstrap;
Marketplace = marketplace;
}
public GethBootstrapNodeInfo Bootstrap { get; }
public MarketplaceInfo Marketplace { get; }
public NethereumInteraction StartInteraction(TestLog log)
{
var ip = Bootstrap.RunningContainers.RunningPod.Cluster.IP;
var port = Bootstrap.RunningContainers.Containers[0].ServicePorts[0].Number;
var account = Bootstrap.Account;
var creator = new NethereumInteractionCreator(log, ip, port, account);
return creator.CreateWorkflow();
}
}
}

57
DistTestCore/Tokens.cs Normal file
View File

@ -0,0 +1,57 @@
namespace DistTestCore
{
public class Ether
{
public Ether(decimal wei)
{
Wei = wei;
}
public decimal Wei { get; }
}
public class TestToken
{
public TestToken(decimal amount)
{
Amount = amount;
}
public decimal Amount { get; }
}
public static class TokensIntExtensions
{
private 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)
{
return Eth(Convert.ToDecimal(i));
}
public static Ether Wei(this int i)
{
return Wei(Convert.ToDecimal(i));
}
public static Ether Eth(this decimal i)
{
return new Ether(i * weiPerEth);
}
public static Ether Wei(this decimal i)
{
return new Ether(i);
}
}
}

View File

@ -30,6 +30,14 @@ namespace NethereumWorkflow
Log($"Transferred {amount} to {account}");
}
public void MintTestTokens(string account, decimal amount)
{
if (amount < 1 || string.IsNullOrEmpty(account)) throw new ArgumentException("Invalid arguments for MintTestTokens");
// - address of token? -> address of marketplace?
// - nethereum do contract call
}
public decimal GetBalance(string account)
{
var bigInt = Time.Wait(web3.Eth.GetBalance.SendRequestAsync(account));

View File

@ -51,7 +51,7 @@ namespace Tests.BasicTests
{
var group = SetupCodexNodes(2)
.WithStorageQuota(10.GB())
.EnableMarketplace(initialBalance: 20)
.EnableMarketplace(20.TestTokens())
.BringOnline();
foreach (var node in group)