diff --git a/DistTestCore/BaseStarter.cs b/DistTestCore/BaseStarter.cs new file mode 100644 index 0000000..e4f7fde --- /dev/null +++ b/DistTestCore/BaseStarter.cs @@ -0,0 +1,39 @@ +using KubernetesWorkflow; + +namespace DistTestCore +{ + public class BaseStarter + { + protected readonly TestLifecycle lifecycle; + protected readonly WorkflowCreator workflowCreator; + private Stopwatch? stopwatch; + + public BaseStarter(TestLifecycle lifecycle, WorkflowCreator workflowCreator) + { + this.lifecycle = lifecycle; + this.workflowCreator = workflowCreator; + } + + protected void LogStart(string msg) + { + Log(msg); + stopwatch = Stopwatch.Begin(lifecycle.Log, GetClassName()); + } + + protected void LogEnd(string msg) + { + stopwatch!.End(msg); + stopwatch = null; + } + + protected void Log(string msg) + { + lifecycle.Log.Log($"{GetClassName} {msg}"); + } + + private string GetClassName() + { + return GetType().Name; + } + } +} diff --git a/DistTestCore/CodexStarter.cs b/DistTestCore/CodexStarter.cs index e90c0f0..9dead26 100644 --- a/DistTestCore/CodexStarter.cs +++ b/DistTestCore/CodexStarter.cs @@ -3,7 +3,7 @@ using KubernetesWorkflow; namespace DistTestCore { - public class CodexStarter + public class CodexStarter // basestarter { private readonly TestLifecycle lifecycle; private readonly WorkflowCreator workflowCreator; diff --git a/DistTestCore/GethStarter.cs b/DistTestCore/GethStarter.cs index dbb19f9..0618078 100644 --- a/DistTestCore/GethStarter.cs +++ b/DistTestCore/GethStarter.cs @@ -3,7 +3,7 @@ using KubernetesWorkflow; namespace DistTestCore { - public class GethStarter + public class GethStarter // basestarter { private readonly MarketplaceNetworkCache marketplaceNetworkCache; private readonly GethCompanionNodeStarter companionNodeStarter; @@ -36,8 +36,10 @@ namespace DistTestCore foreach (var node in companionNodes) { interaction.TransferTo(node.Account, marketplaceConfig.InitialEth.Wei); - // wrong level: mintTestTokens? interactions knows nothing about contract details! - //interaction.MintTestTokens(node.Account, marketplaceConfig.InitialTestTokens.Amount); + + var tokenAddress = interaction.GetTokenAddress(marketplaceNetwork.Marketplace.Address); + + interaction.MintTestTokens(node.Account, marketplaceConfig.InitialTestTokens.Amount, tokenAddress); } } diff --git a/DistTestCore/Marketplace/CodexContractsStarter.cs b/DistTestCore/Marketplace/CodexContractsStarter.cs index c013618..1be0df3 100644 --- a/DistTestCore/Marketplace/CodexContractsStarter.cs +++ b/DistTestCore/Marketplace/CodexContractsStarter.cs @@ -3,24 +3,22 @@ using Utils; namespace DistTestCore.Marketplace { - public class CodexContractsStarter + public class CodexContractsStarter : BaseStarter { private const string readyString = "Done! Sleeping indefinitely..."; - private readonly TestLifecycle lifecycle; - private readonly WorkflowCreator workflowCreator; public CodexContractsStarter(TestLifecycle lifecycle, WorkflowCreator workflowCreator) + : base(lifecycle, workflowCreator) { - this.lifecycle = lifecycle; - this.workflowCreator = workflowCreator; } public MarketplaceInfo Start(RunningContainer bootstrapContainer) { + LogStart("Deploying Codex contracts..."); + var workflow = workflowCreator.CreateWorkflow(); var startupConfig = CreateStartupConfig(bootstrapContainer); - lifecycle.Log.Log("Deploying Codex contracts..."); var containers = workflow.Start(1, Location.Unspecified, new CodexContractsContainerRecipe(), startupConfig); if (containers.Containers.Length != 1) throw new InvalidOperationException("Expected 1 Codex contracts container to be created. Test infra failure."); var container = containers.Containers[0]; @@ -35,7 +33,7 @@ namespace DistTestCore.Marketplace var extractor = new ContainerInfoExtractor(workflow, container); var marketplaceAddress = extractor.ExtractMarketplaceAddress(); - lifecycle.Log.Log("Contracts deployed."); + LogEnd("Contracts deployed."); return new MarketplaceInfo(marketplaceAddress); } diff --git a/DistTestCore/Marketplace/ContainerInfoExtractor.cs b/DistTestCore/Marketplace/ContainerInfoExtractor.cs index 0dc5320..7a9105b 100644 --- a/DistTestCore/Marketplace/ContainerInfoExtractor.cs +++ b/DistTestCore/Marketplace/ContainerInfoExtractor.cs @@ -39,6 +39,14 @@ namespace DistTestCore.Marketplace return pubKey; } + public string ExtractBootstrapPrivateKey() + { + var privKey = Retry(FetchBootstrapPrivateKey); + if (string.IsNullOrEmpty(privKey)) throw new InvalidOperationException("Unable to fetch private key from geth node. Test infra failure."); + + return privKey; + } + public string ExtractMarketplaceAddress() { var marketplaceAddress = Retry(FetchMarketplaceAddress); @@ -80,6 +88,11 @@ namespace DistTestCore.Marketplace return workflow.ExecuteCommand(container, "cat", GethContainerRecipe.AccountFilename); } + private string FetchBootstrapPrivateKey() + { + return workflow.ExecuteCommand(container, "cat", GethContainerRecipe.BootstrapPrivateKeyFilename); + } + private string FetchMarketplaceAddress() { var json = workflow.ExecuteCommand(container, "cat", CodexContractsContainerRecipe.MarketplaceAddressFilename); diff --git a/DistTestCore/Marketplace/GethBootstrapNodeInfo.cs b/DistTestCore/Marketplace/GethBootstrapNodeInfo.cs index be73d36..ab4196f 100644 --- a/DistTestCore/Marketplace/GethBootstrapNodeInfo.cs +++ b/DistTestCore/Marketplace/GethBootstrapNodeInfo.cs @@ -4,12 +4,13 @@ namespace DistTestCore.Marketplace { public class GethBootstrapNodeInfo { - public GethBootstrapNodeInfo(RunningContainers runningContainers, string account, string genesisJsonBase64, string pubKey, Port discoveryPort) + public GethBootstrapNodeInfo(RunningContainers runningContainers, string account, string genesisJsonBase64, string pubKey, string privateKey, Port discoveryPort) { RunningContainers = runningContainers; Account = account; GenesisJsonBase64 = genesisJsonBase64; PubKey = pubKey; + PrivateKey = privateKey; DiscoveryPort = discoveryPort; } @@ -17,6 +18,7 @@ namespace DistTestCore.Marketplace public string Account { get; } public string GenesisJsonBase64 { get; } public string PubKey { get; } + public string PrivateKey { get; } public Port DiscoveryPort { get; } } } diff --git a/DistTestCore/Marketplace/GethBootstrapNodeStarter.cs b/DistTestCore/Marketplace/GethBootstrapNodeStarter.cs index 293555f..494940b 100644 --- a/DistTestCore/Marketplace/GethBootstrapNodeStarter.cs +++ b/DistTestCore/Marketplace/GethBootstrapNodeStarter.cs @@ -2,21 +2,18 @@ namespace DistTestCore.Marketplace { - public class GethBootstrapNodeStarter + public class GethBootstrapNodeStarter : BaseStarter { private const string bootstrapGenesisJsonBase64 = "ewogICAgImNvbmZpZyI6IHsKICAgICAgImNoYWluSWQiOiA3ODk5ODgsCiAgICAgICJob21lc3RlYWRCbG9jayI6IDAsCiAgICAgICJlaXAxNTBCbG9jayI6IDAsCiAgICAgICJlaXAxNTVCbG9jayI6IDAsCiAgICAgICJlaXAxNThCbG9jayI6IDAsCiAgICAgICJieXphbnRpdW1CbG9jayI6IDAsCiAgICAgICJjb25zdGFudGlub3BsZUJsb2NrIjogMCwKICAgICAgInBldGVyc2J1cmdCbG9jayI6IDAsCiAgICAgICJpc3RhbmJ1bEJsb2NrIjogMCwKICAgICAgIm11aXJHbGFjaWVyQmxvY2siOiAwLAogICAgICAiYmVybGluQmxvY2siOiAwLAogICAgICAibG9uZG9uQmxvY2siOiAwLAogICAgICAiYXJyb3dHbGFjaWVyQmxvY2siOiAwLAogICAgICAiZ3JheUdsYWNpZXJCbG9jayI6IDAsCiAgICAgICJjbGlxdWUiOiB7CiAgICAgICAgInBlcmlvZCI6IDUsCiAgICAgICAgImVwb2NoIjogMzAwMDAKICAgICAgfQogICAgfSwKICAgICJkaWZmaWN1bHR5IjogIjEiLAogICAgImdhc0xpbWl0IjogIjgwMDAwMDAwMCIsCiAgICAiZXh0cmFkYXRhIjogIjB4MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMEFDQ09VTlRfSEVSRTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAiLAogICAgImFsbG9jIjogewogICAgICAiMHhBQ0NPVU5UX0hFUkUiOiB7ICJiYWxhbmNlIjogIjUwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAiIH0KICAgIH0KICB9"; - private readonly TestLifecycle lifecycle; - private readonly WorkflowCreator workflowCreator; public GethBootstrapNodeStarter(TestLifecycle lifecycle, WorkflowCreator workflowCreator) + : base(lifecycle, workflowCreator) { - this.lifecycle = lifecycle; - this.workflowCreator = workflowCreator; } public GethBootstrapNodeInfo StartGethBootstrapNode() { - Log("Starting Geth bootstrap node..."); + LogStart("Starting Geth bootstrap node..."); var startupConfig = CreateBootstrapStartupConfig(); var workflow = workflowCreator.CreateWorkflow(); @@ -28,11 +25,12 @@ namespace DistTestCore.Marketplace var account = extractor.ExtractAccount(); var genesisJsonBase64 = extractor.ExtractGenesisJsonBase64(); var pubKey = extractor.ExtractPubKey(); + var privateKey = extractor.ExtractBootstrapPrivateKey(); var discoveryPort = bootstrapContainer.Recipe.GetPortByTag(GethContainerRecipe.DiscoveryPortTag); - Log($"Geth bootstrap node started with account '{account}'"); + LogEnd($"Geth bootstrap node started with account '{account}'"); - return new GethBootstrapNodeInfo(containers, account, genesisJsonBase64, pubKey, discoveryPort); + return new GethBootstrapNodeInfo(containers, account, genesisJsonBase64, pubKey, privateKey, discoveryPort); } private StartupConfig CreateBootstrapStartupConfig() @@ -41,10 +39,5 @@ namespace DistTestCore.Marketplace config.Add(new GethStartupConfig(true, bootstrapGenesisJsonBase64, null!)); return config; } - - private void Log(string msg) - { - lifecycle.Log.Log(msg); - } } } diff --git a/DistTestCore/Marketplace/GethContainerRecipe.cs b/DistTestCore/Marketplace/GethContainerRecipe.cs index 3cb7d41..959daf8 100644 --- a/DistTestCore/Marketplace/GethContainerRecipe.cs +++ b/DistTestCore/Marketplace/GethContainerRecipe.cs @@ -9,7 +9,8 @@ namespace DistTestCore.Marketplace public const string DiscoveryPortTag = "disc_port"; public const string AccountFilename = "account_string.txt"; public const string GenesisFilename = "genesis.json"; - + public const string BootstrapPrivateKeyFilename = "bootstrap_private.key"; + protected override string Image => DockerImage; protected override void Initialize(StartupConfig startupConfig) diff --git a/DistTestCore/Marketplace/MarketplaceNetwork.cs b/DistTestCore/Marketplace/MarketplaceNetwork.cs index 627e6a0..7d27372 100644 --- a/DistTestCore/Marketplace/MarketplaceNetwork.cs +++ b/DistTestCore/Marketplace/MarketplaceNetwork.cs @@ -19,8 +19,9 @@ namespace DistTestCore.Marketplace var ip = Bootstrap.RunningContainers.RunningPod.Cluster.IP; var port = Bootstrap.RunningContainers.Containers[0].ServicePorts[0].Number; var account = Bootstrap.Account; + var privateKey = Bootstrap.PrivateKey; - var creator = new NethereumInteractionCreator(log, ip, port, account); + var creator = new NethereumInteractionCreator(log, ip, port, account, privateKey); return creator.CreateWorkflow(); } } diff --git a/DistTestCore/PrometheusStarter.cs b/DistTestCore/PrometheusStarter.cs index a58b3e4..bd375b8 100644 --- a/DistTestCore/PrometheusStarter.cs +++ b/DistTestCore/PrometheusStarter.cs @@ -5,7 +5,7 @@ using System.Text; namespace DistTestCore { - public class PrometheusStarter + public class PrometheusStarter // basestarter { private readonly TestLifecycle lifecycle; private readonly WorkflowCreator workflowCreator; diff --git a/DistTestCore/Stopwatch.cs b/DistTestCore/Stopwatch.cs index 5be09c0..878912f 100644 --- a/DistTestCore/Stopwatch.cs +++ b/DistTestCore/Stopwatch.cs @@ -5,15 +5,32 @@ namespace DistTestCore { public class Stopwatch { + private readonly DateTime start = DateTime.UtcNow; + private readonly BaseLog log; + private readonly string name; + + public Stopwatch(BaseLog log, string name) + { + this.log = log; + this.name = name; + } + public static void Measure(BaseLog log, string name, Action action) { - var start = DateTime.UtcNow; - + var sw = Begin(log, name); action(); + sw.End(); + } + public static Stopwatch Begin(BaseLog log, string name) + { + return new Stopwatch(log, name); + } + + public void End(string msg = "") + { var duration = DateTime.UtcNow - start; - - log.Log($"{name} ({Time.FormatDuration(duration)})"); + log.Log($"{name} {msg} ({Time.FormatDuration(duration)})"); } } } diff --git a/Nethereum/NethereumInteraction.cs b/Nethereum/NethereumInteraction.cs index a135bd8..9092524 100644 --- a/Nethereum/NethereumInteraction.cs +++ b/Nethereum/NethereumInteraction.cs @@ -1,4 +1,6 @@ using Logging; +using Nethereum.ABI.FunctionEncoding.Attributes; +using Nethereum.Contracts; using Nethereum.Hex.HexTypes; using Nethereum.Web3; using System.Numerics; @@ -30,12 +32,28 @@ namespace NethereumWorkflow Log($"Transferred {amount} to {account}"); } - public void MintTestTokens(string account, decimal amount) + public string GetTokenAddress(string marketplaceAddress) + { + var function = new GetTokenFunction(); + + var handler = web3.Eth.GetContractQueryHandler(); + var result = Time.Wait(handler.QueryAsync(marketplaceAddress, function)); + + return result; + } + + public void MintTestTokens(string account, decimal amount, string tokenAddress) { if (amount < 1 || string.IsNullOrEmpty(account)) throw new ArgumentException("Invalid arguments for MintTestTokens"); - // - address of token? -> address of marketplace? - // - nethereum do contract call + var function = new MintTokensFunction + { + Holder = account, + Amount = ToBig(amount) + }; + + var handler = web3.Eth.GetContractTransactionHandler(); + Time.Wait(handler.SendRequestAndWaitForReceiptAsync(tokenAddress, function)); } public decimal GetBalance(string account) @@ -48,11 +66,16 @@ namespace NethereumWorkflow private HexBigInteger ToHexBig(decimal amount) { - var bigint = new BigInteger(amount); + var bigint = ToBig(amount); var str = bigint.ToString("X"); return new HexBigInteger(str); } + private BigInteger ToBig(decimal amount) + { + return new BigInteger(amount); + } + private decimal ToDecimal(HexBigInteger hexBigInteger) { return (decimal)hexBigInteger.Value; @@ -63,4 +86,19 @@ namespace NethereumWorkflow log.Log(msg); } } + + [Function("token", "address")] + public class GetTokenFunction : FunctionMessage + { + } + + [Function("mint")] + public class MintTokensFunction : FunctionMessage + { + [Parameter("address", "holder", 1)] + public string Holder { get; set; } + + [Parameter("uint256", "amount", 2)] + public BigInteger Amount { get; set; } + } } diff --git a/Nethereum/NethereumInteractionCreator.cs b/Nethereum/NethereumInteractionCreator.cs index b0b41f7..3695fa1 100644 --- a/Nethereum/NethereumInteractionCreator.cs +++ b/Nethereum/NethereumInteractionCreator.cs @@ -9,13 +9,15 @@ namespace NethereumWorkflow private readonly string ip; private readonly int port; private readonly string rootAccount; + private readonly string privateKey; - public NethereumInteractionCreator(TestLog log, string ip, int port, string rootAccount) + public NethereumInteractionCreator(TestLog log, string ip, int port, string rootAccount, string privateKey) { this.log = log; this.ip = ip; this.port = port; this.rootAccount = rootAccount; + this.privateKey = privateKey; } public NethereumInteraction CreateWorkflow() @@ -25,8 +27,8 @@ namespace NethereumWorkflow private Web3 CreateWeb3() { - //var bootstrapaccount = new ManagedAccount(bootstrapInfo.Account, "qwerty!@#$%^"); - return new Web3($"http://{ip}:{port}"); + var account = new Nethereum.Web3.Accounts.Account(privateKey); + return new Web3(account, $"http://{ip}:{port}"); } } }