Applies faster geth image
This commit is contained in:
parent
ea0a690862
commit
01c8238311
|
@ -36,13 +36,8 @@ namespace DistTestCore
|
||||||
var interaction = marketplaceNetwork.StartInteraction(lifecycle.Log);
|
var interaction = marketplaceNetwork.StartInteraction(lifecycle.Log);
|
||||||
var tokenAddress = marketplaceNetwork.Marketplace.TokenAddress;
|
var tokenAddress = marketplaceNetwork.Marketplace.TokenAddress;
|
||||||
|
|
||||||
foreach (var account in companionNode.Accounts)
|
var accounts = companionNode.Accounts.Select(a => a.Account).ToArray();
|
||||||
{
|
interaction.MintTestTokens(accounts, marketplaceConfig.InitialTestTokens.Amount, tokenAddress);
|
||||||
interaction.TransferWeiTo(account.Account, marketplaceConfig.InitialEth.Wei);
|
|
||||||
interaction.MintTestTokens(account.Account, marketplaceConfig.InitialTestTokens.Amount, tokenAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
interaction.WaitForAllTransactions();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private GethStartResult CreateGethStartResult(MarketplaceNetwork marketplaceNetwork, GethCompanionNodeInfo companionNode)
|
private GethStartResult CreateGethStartResult(MarketplaceNetwork marketplaceNetwork, GethCompanionNodeInfo companionNode)
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace DistTestCore.Marketplace
|
||||||
#if Arm64
|
#if Arm64
|
||||||
public const string DockerImage = "emizzle/codex-contracts-deployment:latest";
|
public const string DockerImage = "emizzle/codex-contracts-deployment:latest";
|
||||||
#else
|
#else
|
||||||
public const string DockerImage = "thatbenbierens/codex-contracts-deployment";
|
public const string DockerImage = "thatbenbierens/codex-contracts-deployment:nomint";
|
||||||
#endif
|
#endif
|
||||||
public const string MarketplaceAddressFilename = "/usr/app/deployments/codexdisttestnetwork/Marketplace.json";
|
public const string MarketplaceAddressFilename = "/usr/app/deployments/codexdisttestnetwork/Marketplace.json";
|
||||||
public const string MarketplaceArtifactFilename = "/usr/app/artifacts/contracts/Marketplace.sol/Marketplace.json";
|
public const string MarketplaceArtifactFilename = "/usr/app/artifacts/contracts/Marketplace.sol/Marketplace.json";
|
||||||
|
|
|
@ -19,13 +19,14 @@ namespace DistTestCore.Marketplace
|
||||||
this.container = container;
|
this.container = container;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ExtractAccount(int? orderNumber)
|
public AllGethAccounts ExtractAccounts()
|
||||||
{
|
{
|
||||||
log.Debug();
|
log.Debug();
|
||||||
var account = Retry(() => FetchAccount(orderNumber));
|
var accountsCsv = Retry(() => FetchAccountsCsv());
|
||||||
if (string.IsNullOrEmpty(account)) throw new InvalidOperationException("Unable to fetch account for geth node. Test infra failure.");
|
if (string.IsNullOrEmpty(accountsCsv)) throw new InvalidOperationException("Unable to fetch accounts.csv for geth node. Test infra failure.");
|
||||||
|
|
||||||
return account;
|
var lines = accountsCsv.Split('\n');
|
||||||
|
return new AllGethAccounts(lines.Select(ParseLineToAccount).ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ExtractPubKey()
|
public string ExtractPubKey()
|
||||||
|
@ -37,15 +38,6 @@ namespace DistTestCore.Marketplace
|
||||||
return pubKey;
|
return pubKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ExtractPrivateKey(int? orderNumber)
|
|
||||||
{
|
|
||||||
log.Debug();
|
|
||||||
var privKey = Retry(() => FetchPrivateKey(orderNumber));
|
|
||||||
if (string.IsNullOrEmpty(privKey)) throw new InvalidOperationException("Unable to fetch private key from geth node. Test infra failure.");
|
|
||||||
|
|
||||||
return privKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ExtractMarketplaceAddress()
|
public string ExtractMarketplaceAddress()
|
||||||
{
|
{
|
||||||
log.Debug();
|
log.Debug();
|
||||||
|
@ -88,14 +80,9 @@ namespace DistTestCore.Marketplace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string FetchAccount(int? orderNumber)
|
private string FetchAccountsCsv()
|
||||||
{
|
{
|
||||||
return workflow.ExecuteCommand(container, "cat", GethContainerRecipe.GetAccountFilename(orderNumber));
|
return workflow.ExecuteCommand(container, "cat", GethContainerRecipe.AccountsFilename);
|
||||||
}
|
|
||||||
|
|
||||||
private string FetchPrivateKey(int? orderNumber)
|
|
||||||
{
|
|
||||||
return workflow.ExecuteCommand(container, "cat", GethContainerRecipe.GetPrivateKeyFilename(orderNumber));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private string FetchMarketplaceAddress()
|
private string FetchMarketplaceAddress()
|
||||||
|
@ -120,6 +107,15 @@ namespace DistTestCore.Marketplace
|
||||||
workflow.DownloadContainerLog(container, enodeFinder);
|
workflow.DownloadContainerLog(container, enodeFinder);
|
||||||
return enodeFinder.GetPubKey();
|
return enodeFinder.GetPubKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private GethAccount ParseLineToAccount(string l)
|
||||||
|
{
|
||||||
|
var tokens = l.Replace("\r", "").Split(',');
|
||||||
|
if (tokens.Length != 2) throw new InvalidOperationException();
|
||||||
|
var account = tokens[0];
|
||||||
|
var privateKey = tokens[1];
|
||||||
|
return new GethAccount(account, privateKey);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PubKeyFinder : LogHandler, ILogHandler
|
public class PubKeyFinder : LogHandler, ILogHandler
|
||||||
|
|
|
@ -6,19 +6,19 @@ namespace DistTestCore.Marketplace
|
||||||
{
|
{
|
||||||
public class GethBootstrapNodeInfo
|
public class GethBootstrapNodeInfo
|
||||||
{
|
{
|
||||||
public GethBootstrapNodeInfo(RunningContainers runningContainers, string account, string pubKey, string privateKey, Port discoveryPort)
|
public GethBootstrapNodeInfo(RunningContainers runningContainers, AllGethAccounts allAccounts, string pubKey, Port discoveryPort)
|
||||||
{
|
{
|
||||||
RunningContainers = runningContainers;
|
RunningContainers = runningContainers;
|
||||||
Account = account;
|
AllAccounts = allAccounts;
|
||||||
|
Account = allAccounts.Accounts[0];
|
||||||
PubKey = pubKey;
|
PubKey = pubKey;
|
||||||
PrivateKey = privateKey;
|
|
||||||
DiscoveryPort = discoveryPort;
|
DiscoveryPort = discoveryPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RunningContainers RunningContainers { get; }
|
public RunningContainers RunningContainers { get; }
|
||||||
public string Account { get; }
|
public AllGethAccounts AllAccounts { get; }
|
||||||
|
public GethAccount Account { get; }
|
||||||
public string PubKey { get; }
|
public string PubKey { get; }
|
||||||
public string PrivateKey { get; }
|
|
||||||
public Port DiscoveryPort { get; }
|
public Port DiscoveryPort { get; }
|
||||||
|
|
||||||
public NethereumInteraction StartInteraction(BaseLog log)
|
public NethereumInteraction StartInteraction(BaseLog log)
|
||||||
|
@ -26,10 +26,19 @@ namespace DistTestCore.Marketplace
|
||||||
var ip = RunningContainers.RunningPod.Cluster.IP;
|
var ip = RunningContainers.RunningPod.Cluster.IP;
|
||||||
var port = RunningContainers.Containers[0].ServicePorts[0].Number;
|
var port = RunningContainers.Containers[0].ServicePorts[0].Number;
|
||||||
var account = Account;
|
var account = Account;
|
||||||
var privateKey = PrivateKey;
|
|
||||||
|
|
||||||
var creator = new NethereumInteractionCreator(log, ip, port, account, privateKey);
|
var creator = new NethereumInteractionCreator(log, ip, port, account.PrivateKey);
|
||||||
return creator.CreateWorkflow();
|
return creator.CreateWorkflow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class AllGethAccounts
|
||||||
|
{
|
||||||
|
public GethAccount[] Accounts { get; }
|
||||||
|
|
||||||
|
public AllGethAccounts(GethAccount[] accounts)
|
||||||
|
{
|
||||||
|
Accounts = accounts;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,20 +20,20 @@ namespace DistTestCore.Marketplace
|
||||||
var bootstrapContainer = containers.Containers[0];
|
var bootstrapContainer = containers.Containers[0];
|
||||||
|
|
||||||
var extractor = new ContainerInfoExtractor(lifecycle.Log, workflow, bootstrapContainer);
|
var extractor = new ContainerInfoExtractor(lifecycle.Log, workflow, bootstrapContainer);
|
||||||
var account = extractor.ExtractAccount(null);
|
var accounts = extractor.ExtractAccounts();
|
||||||
var pubKey = extractor.ExtractPubKey();
|
var pubKey = extractor.ExtractPubKey();
|
||||||
var privateKey = extractor.ExtractPrivateKey(null);
|
|
||||||
var discoveryPort = bootstrapContainer.Recipe.GetPortByTag(GethContainerRecipe.DiscoveryPortTag);
|
var discoveryPort = bootstrapContainer.Recipe.GetPortByTag(GethContainerRecipe.DiscoveryPortTag);
|
||||||
|
var result = new GethBootstrapNodeInfo(containers, accounts, pubKey, discoveryPort);
|
||||||
|
|
||||||
LogEnd($"Geth bootstrap node started with account '{account}'");
|
LogEnd($"Geth bootstrap node started with account '{result.Account.Account}'");
|
||||||
|
|
||||||
return new GethBootstrapNodeInfo(containers, account, pubKey, privateKey, discoveryPort);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private StartupConfig CreateBootstrapStartupConfig()
|
private StartupConfig CreateBootstrapStartupConfig()
|
||||||
{
|
{
|
||||||
var config = new StartupConfig();
|
var config = new StartupConfig();
|
||||||
config.Add(new GethStartupConfig(true, null!, 0));
|
config.Add(new GethStartupConfig(true, null!, 0, 0));
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,30 +6,29 @@ namespace DistTestCore.Marketplace
|
||||||
{
|
{
|
||||||
public class GethCompanionNodeInfo
|
public class GethCompanionNodeInfo
|
||||||
{
|
{
|
||||||
public GethCompanionNodeInfo(RunningContainer runningContainer, GethCompanionAccount[] accounts)
|
public GethCompanionNodeInfo(RunningContainer runningContainer, GethAccount[] accounts)
|
||||||
{
|
{
|
||||||
RunningContainer = runningContainer;
|
RunningContainer = runningContainer;
|
||||||
Accounts = accounts;
|
Accounts = accounts;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RunningContainer RunningContainer { get; }
|
public RunningContainer RunningContainer { get; }
|
||||||
public GethCompanionAccount[] Accounts { get; }
|
public GethAccount[] Accounts { get; }
|
||||||
|
|
||||||
public NethereumInteraction StartInteraction(BaseLog log, GethCompanionAccount account)
|
public NethereumInteraction StartInteraction(BaseLog log, GethAccount account)
|
||||||
{
|
{
|
||||||
var ip = RunningContainer.Pod.Cluster.IP;
|
var ip = RunningContainer.Pod.Cluster.IP;
|
||||||
var port = RunningContainer.ServicePorts[0].Number;
|
var port = RunningContainer.ServicePorts[0].Number;
|
||||||
var accountStr = account.Account;
|
|
||||||
var privateKey = account.PrivateKey;
|
var privateKey = account.PrivateKey;
|
||||||
|
|
||||||
var creator = new NethereumInteractionCreator(log, ip, port, accountStr, privateKey);
|
var creator = new NethereumInteractionCreator(log, ip, port, privateKey);
|
||||||
return creator.CreateWorkflow();
|
return creator.CreateWorkflow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class GethCompanionAccount
|
public class GethAccount
|
||||||
{
|
{
|
||||||
public GethCompanionAccount(string account, string privateKey)
|
public GethAccount(string account, string privateKey)
|
||||||
{
|
{
|
||||||
Account = account;
|
Account = account;
|
||||||
PrivateKey = privateKey;
|
PrivateKey = privateKey;
|
||||||
|
|
|
@ -5,6 +5,8 @@ namespace DistTestCore.Marketplace
|
||||||
{
|
{
|
||||||
public class GethCompanionNodeStarter : BaseStarter
|
public class GethCompanionNodeStarter : BaseStarter
|
||||||
{
|
{
|
||||||
|
private int companionAccountIndex = 0;
|
||||||
|
|
||||||
public GethCompanionNodeStarter(TestLifecycle lifecycle, WorkflowCreator workflowCreator)
|
public GethCompanionNodeStarter(TestLifecycle lifecycle, WorkflowCreator workflowCreator)
|
||||||
: base(lifecycle, workflowCreator)
|
: base(lifecycle, workflowCreator)
|
||||||
{
|
{
|
||||||
|
@ -14,53 +16,43 @@ namespace DistTestCore.Marketplace
|
||||||
{
|
{
|
||||||
LogStart($"Initializing companion for {codexSetup.NumberOfNodes} Codex nodes.");
|
LogStart($"Initializing companion for {codexSetup.NumberOfNodes} Codex nodes.");
|
||||||
|
|
||||||
var startupConfig = CreateCompanionNodeStartupConfig(marketplace.Bootstrap, codexSetup.NumberOfNodes);
|
var config = CreateCompanionNodeStartupConfig(marketplace.Bootstrap, codexSetup.NumberOfNodes);
|
||||||
|
|
||||||
var workflow = workflowCreator.CreateWorkflow();
|
var workflow = workflowCreator.CreateWorkflow();
|
||||||
var containers = workflow.Start(1, Location.Unspecified, new GethContainerRecipe(), startupConfig);
|
var containers = workflow.Start(1, Location.Unspecified, new GethContainerRecipe(), CreateStartupConfig(config));
|
||||||
WaitForAccountCreation(codexSetup.NumberOfNodes);
|
|
||||||
if (containers.Containers.Length != 1) throw new InvalidOperationException("Expected one Geth companion node to be created. Test infra failure.");
|
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 container = containers.Containers[0];
|
||||||
|
|
||||||
var node = CreateCompanionInfo(workflow, container, codexSetup.NumberOfNodes);
|
var node = CreateCompanionInfo(container, marketplace, config);
|
||||||
EnsureCompanionNodeIsSynced(node, marketplace);
|
EnsureCompanionNodeIsSynced(node, marketplace);
|
||||||
|
|
||||||
LogEnd($"Initialized one companion node for {codexSetup.NumberOfNodes} Codex nodes. Their accounts: [{string.Join(",", node.Accounts.Select(a => a.Account))}]");
|
LogEnd($"Initialized one companion node for {codexSetup.NumberOfNodes} Codex nodes. Their accounts: [{string.Join(",", node.Accounts.Select(a => a.Account))}]");
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WaitForAccountCreation(int numberOfNodes)
|
private GethCompanionNodeInfo CreateCompanionInfo(RunningContainer container, MarketplaceNetwork marketplace, GethStartupConfig config)
|
||||||
{
|
{
|
||||||
// We wait proportional to the number of account the node has to create. It takes a few seconds for each one to generate the keys and create the files
|
var accounts = ExtractAccounts(marketplace, config);
|
||||||
// we will be trying to read in 'ExtractAccount', later on in the start-up process.
|
|
||||||
Time.Sleep(TimeSpan.FromSeconds(4.5 * numberOfNodes));
|
|
||||||
}
|
|
||||||
|
|
||||||
private GethCompanionNodeInfo CreateCompanionInfo(StartupWorkflow workflow, RunningContainer container, int numberOfAccounts)
|
|
||||||
{
|
|
||||||
var extractor = new ContainerInfoExtractor(lifecycle.Log, workflow, container);
|
|
||||||
var accounts = ExtractAccounts(extractor, numberOfAccounts).ToArray();
|
|
||||||
return new GethCompanionNodeInfo(container, accounts);
|
return new GethCompanionNodeInfo(container, accounts);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<GethCompanionAccount> ExtractAccounts(ContainerInfoExtractor extractor, int numberOfAccounts)
|
private static GethAccount[] ExtractAccounts(MarketplaceNetwork marketplace, GethStartupConfig config)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < numberOfAccounts; i++) yield return ExtractAccount(extractor, i + 1);
|
return marketplace.Bootstrap.AllAccounts.Accounts
|
||||||
}
|
.Skip(1 + config.CompanionAccountStartIndex)
|
||||||
|
.Take(config.NumberOfCompanionAccounts)
|
||||||
private GethCompanionAccount ExtractAccount(ContainerInfoExtractor extractor, int orderNumber)
|
.ToArray();
|
||||||
{
|
|
||||||
var account = extractor.ExtractAccount(orderNumber);
|
|
||||||
var privKey = extractor.ExtractPrivateKey(orderNumber);
|
|
||||||
return new GethCompanionAccount(account, privKey);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EnsureCompanionNodeIsSynced(GethCompanionNodeInfo node, MarketplaceNetwork marketplace)
|
private void EnsureCompanionNodeIsSynced(GethCompanionNodeInfo node, MarketplaceNetwork marketplace)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var interaction = node.StartInteraction(lifecycle.Log, node.Accounts.First());
|
Time.WaitUntil(() =>
|
||||||
interaction.EnsureSynced(marketplace.Marketplace.Address, marketplace.Marketplace.Abi);
|
{
|
||||||
|
var interaction = node.StartInteraction(lifecycle.Log, node.Accounts.First());
|
||||||
|
return interaction.IsSynced(marketplace.Marketplace.Address, marketplace.Marketplace.Abi);
|
||||||
|
}, TimeSpan.FromMinutes(1), TimeSpan.FromSeconds(3));
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -68,10 +60,17 @@ namespace DistTestCore.Marketplace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private StartupConfig CreateCompanionNodeStartupConfig(GethBootstrapNodeInfo bootstrapNode, int numberOfAccounts)
|
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();
|
var config = new StartupConfig();
|
||||||
config.Add(new GethStartupConfig(false, bootstrapNode, numberOfAccounts));
|
config.Add(gethConfig);
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,23 +7,14 @@ namespace DistTestCore.Marketplace
|
||||||
#if Arm64
|
#if Arm64
|
||||||
public const string DockerImage = "emizzle/geth-confenv:latest";
|
public const string DockerImage = "emizzle/geth-confenv:latest";
|
||||||
#else
|
#else
|
||||||
public const string DockerImage = "thatbenbierens/geth-confenv:latest";
|
public const string DockerImage = "thatbenbierens/geth-confenv:onethousand";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public const string HttpPortTag = "http_port";
|
public const string HttpPortTag = "http_port";
|
||||||
public const string DiscoveryPortTag = "disc_port";
|
public const string DiscoveryPortTag = "disc_port";
|
||||||
private const string defaultArgs = "--ipcdisable --syncmode full";
|
private const string defaultArgs = "--ipcdisable --syncmode full";
|
||||||
|
|
||||||
public static string GetAccountFilename(int? orderNumber)
|
public const string AccountsFilename = "accounts.csv";
|
||||||
{
|
|
||||||
if (orderNumber == null) return "account_string.txt";
|
|
||||||
return $"account_string_{orderNumber.Value}.txt";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetPrivateKeyFilename(int? orderNumber)
|
|
||||||
{
|
|
||||||
if (orderNumber == null) return "private.key";
|
|
||||||
return $"private_{orderNumber.Value}.key";
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override string Image => DockerImage;
|
protected override string Image => DockerImage;
|
||||||
|
|
||||||
|
@ -50,14 +41,17 @@ namespace DistTestCore.Marketplace
|
||||||
|
|
||||||
private string CreateBootstapArgs(Port discovery)
|
private string CreateBootstapArgs(Port discovery)
|
||||||
{
|
{
|
||||||
AddEnvVar("IS_BOOTSTRAP", "1");
|
AddEnvVar("ENABLE_MINER", "1");
|
||||||
|
UnlockAccounts(0, 1);
|
||||||
var exposedPort = AddExposedPort(tag: HttpPortTag);
|
var exposedPort = AddExposedPort(tag: HttpPortTag);
|
||||||
return $"--http.port {exposedPort.Number} --port {discovery.Number} --discovery.port {discovery.Number} {defaultArgs}";
|
return $"--http.port {exposedPort.Number} --port {discovery.Number} --discovery.port {discovery.Number} {defaultArgs}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string CreateCompanionArgs(Port discovery, GethStartupConfig config)
|
private string CreateCompanionArgs(Port discovery, GethStartupConfig config)
|
||||||
{
|
{
|
||||||
AddEnvVar("NUMBER_OF_ACCOUNTS", config.NumberOfCompanionAccounts.ToString());
|
UnlockAccounts(
|
||||||
|
config.CompanionAccountStartIndex + 1,
|
||||||
|
config.NumberOfCompanionAccounts);
|
||||||
|
|
||||||
var port = AddInternalPort();
|
var port = AddInternalPort();
|
||||||
var authRpc = AddInternalPort();
|
var authRpc = AddInternalPort();
|
||||||
|
@ -70,5 +64,15 @@ namespace DistTestCore.Marketplace
|
||||||
|
|
||||||
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}";
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,15 +2,17 @@
|
||||||
{
|
{
|
||||||
public class GethStartupConfig
|
public class GethStartupConfig
|
||||||
{
|
{
|
||||||
public GethStartupConfig(bool isBootstrapNode, GethBootstrapNodeInfo bootstrapNode, int numberOfCompanionAccounts)
|
public GethStartupConfig(bool isBootstrapNode, GethBootstrapNodeInfo bootstrapNode, int companionAccountStartIndex, int numberOfCompanionAccounts)
|
||||||
{
|
{
|
||||||
IsBootstrapNode = isBootstrapNode;
|
IsBootstrapNode = isBootstrapNode;
|
||||||
BootstrapNode = bootstrapNode;
|
BootstrapNode = bootstrapNode;
|
||||||
|
CompanionAccountStartIndex = companionAccountStartIndex;
|
||||||
NumberOfCompanionAccounts = numberOfCompanionAccounts;
|
NumberOfCompanionAccounts = numberOfCompanionAccounts;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsBootstrapNode { get; }
|
public bool IsBootstrapNode { get; }
|
||||||
public GethBootstrapNodeInfo BootstrapNode { get; }
|
public GethBootstrapNodeInfo BootstrapNode { get; }
|
||||||
|
public int CompanionAccountStartIndex { get; }
|
||||||
public int NumberOfCompanionAccounts { get; }
|
public int NumberOfCompanionAccounts { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,10 @@ namespace DistTestCore.Marketplace
|
||||||
{
|
{
|
||||||
private readonly TestLog log;
|
private readonly TestLog log;
|
||||||
private readonly MarketplaceNetwork marketplaceNetwork;
|
private readonly MarketplaceNetwork marketplaceNetwork;
|
||||||
private readonly GethCompanionAccount account;
|
private readonly GethAccount account;
|
||||||
private readonly CodexAccess codexAccess;
|
private readonly CodexAccess codexAccess;
|
||||||
|
|
||||||
public MarketplaceAccess(TestLog log, MarketplaceNetwork marketplaceNetwork, GethCompanionAccount account, CodexAccess codexAccess)
|
public MarketplaceAccess(TestLog log, MarketplaceNetwork marketplaceNetwork, GethAccount account, CodexAccess codexAccess)
|
||||||
{
|
{
|
||||||
this.log = log;
|
this.log = log;
|
||||||
this.marketplaceNetwork = marketplaceNetwork;
|
this.marketplaceNetwork = marketplaceNetwork;
|
||||||
|
|
|
@ -33,10 +33,10 @@ namespace DistTestCore.Marketplace
|
||||||
return new MarketplaceAccess(log, marketplaceNetwork, companionNode, access);
|
return new MarketplaceAccess(log, marketplaceNetwork, companionNode, access);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GethCompanionAccount GetGethCompanionNode(CodexAccess access)
|
private GethAccount GetGethCompanionNode(CodexAccess access)
|
||||||
{
|
{
|
||||||
var account = access.Container.Recipe.Additionals.Single(a => a is GethCompanionAccount);
|
var account = access.Container.Recipe.Additionals.Single(a => a is GethAccount);
|
||||||
return (GethCompanionAccount)account;
|
return (GethAccount)account;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,16 +10,13 @@ namespace NethereumWorkflow
|
||||||
{
|
{
|
||||||
public class NethereumInteraction
|
public class NethereumInteraction
|
||||||
{
|
{
|
||||||
private readonly List<Task> openTasks = new List<Task>();
|
|
||||||
private readonly BaseLog log;
|
private readonly BaseLog log;
|
||||||
private readonly Web3 web3;
|
private readonly Web3 web3;
|
||||||
private readonly string rootAccount;
|
|
||||||
|
|
||||||
internal NethereumInteraction(BaseLog log, Web3 web3, string rootAccount)
|
internal NethereumInteraction(BaseLog log, Web3 web3)
|
||||||
{
|
{
|
||||||
this.log = log;
|
this.log = log;
|
||||||
this.web3 = web3;
|
this.web3 = web3;
|
||||||
this.rootAccount = rootAccount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetTokenAddress(string marketplaceAddress)
|
public string GetTokenAddress(string marketplaceAddress)
|
||||||
|
@ -31,29 +28,13 @@ namespace NethereumWorkflow
|
||||||
return Time.Wait(handler.QueryAsync<string>(marketplaceAddress, function));
|
return Time.Wait(handler.QueryAsync<string>(marketplaceAddress, function));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TransferWeiTo(string account, decimal amount)
|
public void MintTestTokens(string[] accounts, decimal amount, string tokenAddress)
|
||||||
{
|
{
|
||||||
log.Debug($"{amount} --> {account}");
|
if (amount < 1 || accounts.Length < 1) throw new ArgumentException("Invalid arguments for MintTestTokens");
|
||||||
if (amount < 1 || string.IsNullOrEmpty(account)) throw new ArgumentException("Invalid arguments for AddToBalance");
|
|
||||||
|
|
||||||
var value = ToHexBig(amount);
|
var tasks = accounts.Select(a => MintTokens(a, amount, tokenAddress));
|
||||||
var transactionId = Time.Wait(web3.Eth.TransactionManager.SendTransactionAsync(rootAccount, account, value));
|
|
||||||
openTasks.Add(web3.Eth.TransactionManager.TransactionReceiptService.PollForReceiptAsync(transactionId));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void MintTestTokens(string account, decimal amount, string tokenAddress)
|
Task.WaitAll(tasks.ToArray());
|
||||||
{
|
|
||||||
log.Debug($"({tokenAddress}) {amount} --> {account}");
|
|
||||||
if (amount < 1 || string.IsNullOrEmpty(account)) throw new ArgumentException("Invalid arguments for MintTestTokens");
|
|
||||||
|
|
||||||
var function = new MintTokensFunction
|
|
||||||
{
|
|
||||||
Holder = account,
|
|
||||||
Amount = ToBig(amount)
|
|
||||||
};
|
|
||||||
|
|
||||||
var handler = web3.Eth.GetContractTransactionHandler<MintTokensFunction>();
|
|
||||||
openTasks.Add(handler.SendRequestAndWaitForReceiptAsync(tokenAddress, function));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public decimal GetBalance(string tokenAddress, string account)
|
public decimal GetBalance(string tokenAddress, string account)
|
||||||
|
@ -68,48 +49,54 @@ namespace NethereumWorkflow
|
||||||
return ToDecimal(Time.Wait(handler.QueryAsync<BigInteger>(tokenAddress, function)));
|
return ToDecimal(Time.Wait(handler.QueryAsync<BigInteger>(tokenAddress, function)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WaitForAllTransactions()
|
public bool IsSynced(string marketplaceAddress, string marketplaceAbi)
|
||||||
{
|
{
|
||||||
var tasks = openTasks.ToArray();
|
try
|
||||||
openTasks.Clear();
|
{
|
||||||
|
return IsBlockNumberOK() && IsContractAvailable(marketplaceAddress, marketplaceAbi);
|
||||||
Task.WaitAll(tasks);
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EnsureSynced(string marketplaceAddress, string marketplaceAbi)
|
private Task MintTokens(string account, decimal amount, string tokenAddress)
|
||||||
{
|
{
|
||||||
WaitUntilSynced();
|
log.Debug($"({tokenAddress}) {amount} --> {account}");
|
||||||
WaitForContract(marketplaceAddress, marketplaceAbi);
|
if (string.IsNullOrEmpty(account)) throw new ArgumentException("Invalid arguments for MintTestTokens");
|
||||||
|
|
||||||
|
var function = new MintTokensFunction
|
||||||
|
{
|
||||||
|
Holder = account,
|
||||||
|
Amount = ToBig(amount)
|
||||||
|
};
|
||||||
|
|
||||||
|
var handler = web3.Eth.GetContractTransactionHandler<MintTokensFunction>();
|
||||||
|
return handler.SendRequestAndWaitForReceiptAsync(tokenAddress, function);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WaitUntilSynced()
|
private bool IsBlockNumberOK()
|
||||||
{
|
{
|
||||||
log.Debug();
|
log.Debug();
|
||||||
Time.WaitUntil(() =>
|
var sync = Time.Wait(web3.Eth.Syncing.SendRequestAsync());
|
||||||
{
|
var number = Time.Wait(web3.Eth.Blocks.GetBlockNumber.SendRequestAsync());
|
||||||
var sync = Time.Wait(web3.Eth.Syncing.SendRequestAsync());
|
var numberOfBlocks = ToDecimal(number);
|
||||||
var number = Time.Wait(web3.Eth.Blocks.GetBlockNumber.SendRequestAsync());
|
return !sync.IsSyncing && numberOfBlocks > 256;
|
||||||
var numberOfBlocks = ToDecimal(number);
|
|
||||||
return !sync.IsSyncing && numberOfBlocks > 256;
|
|
||||||
|
|
||||||
}, TimeSpan.FromMinutes(1), TimeSpan.FromSeconds(3));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WaitForContract(string marketplaceAddress, string marketplaceAbi)
|
private bool IsContractAvailable(string marketplaceAddress, string marketplaceAbi)
|
||||||
{
|
{
|
||||||
log.Debug();
|
log.Debug();
|
||||||
Time.WaitUntil(() =>
|
try
|
||||||
{
|
{
|
||||||
try
|
var contract = web3.Eth.GetContract(marketplaceAbi, marketplaceAddress);
|
||||||
{
|
return contract != null;
|
||||||
var contract = web3.Eth.GetContract(marketplaceAbi, marketplaceAddress);
|
}
|
||||||
return contract != null;
|
catch
|
||||||
}
|
{
|
||||||
catch
|
return false;
|
||||||
{
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}, TimeSpan.FromMinutes(1), TimeSpan.FromSeconds(3));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private HexBigInteger ToHexBig(decimal amount)
|
private HexBigInteger ToHexBig(decimal amount)
|
||||||
|
|
|
@ -8,21 +8,19 @@ namespace NethereumWorkflow
|
||||||
private readonly BaseLog log;
|
private readonly BaseLog log;
|
||||||
private readonly string ip;
|
private readonly string ip;
|
||||||
private readonly int port;
|
private readonly int port;
|
||||||
private readonly string rootAccount;
|
|
||||||
private readonly string privateKey;
|
private readonly string privateKey;
|
||||||
|
|
||||||
public NethereumInteractionCreator(BaseLog log, string ip, int port, string rootAccount, string privateKey)
|
public NethereumInteractionCreator(BaseLog log, string ip, int port, string privateKey)
|
||||||
{
|
{
|
||||||
this.log = log;
|
this.log = log;
|
||||||
this.ip = ip;
|
this.ip = ip;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
this.rootAccount = rootAccount;
|
|
||||||
this.privateKey = privateKey;
|
this.privateKey = privateKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NethereumInteraction CreateWorkflow()
|
public NethereumInteraction CreateWorkflow()
|
||||||
{
|
{
|
||||||
return new NethereumInteraction(log, CreateWeb3(), rootAccount);
|
return new NethereumInteraction(log, CreateWeb3());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Web3 CreateWeb3()
|
private Web3 CreateWeb3()
|
||||||
|
|
|
@ -71,13 +71,13 @@ namespace Tests.BasicTests
|
||||||
requiredCollateral: 10.TestTokens(),
|
requiredCollateral: 10.TestTokens(),
|
||||||
minRequiredNumberOfNodes: 1,
|
minRequiredNumberOfNodes: 1,
|
||||||
proofProbability: 5,
|
proofProbability: 5,
|
||||||
duration: TimeSpan.FromMinutes(2));
|
duration: TimeSpan.FromMinutes(1));
|
||||||
|
|
||||||
Time.Sleep(TimeSpan.FromMinutes(1));
|
Time.Sleep(TimeSpan.FromSeconds(10));
|
||||||
|
|
||||||
seller.Marketplace.AssertThatBalance(Is.LessThan(sellerInitialBalance), "Collateral was not placed.");
|
seller.Marketplace.AssertThatBalance(Is.LessThan(sellerInitialBalance), "Collateral was not placed.");
|
||||||
|
|
||||||
Time.Sleep(TimeSpan.FromMinutes(2));
|
Time.Sleep(TimeSpan.FromMinutes(1));
|
||||||
|
|
||||||
seller.Marketplace.AssertThatBalance(Is.GreaterThan(sellerInitialBalance), "Seller was not paid for storage.");
|
seller.Marketplace.AssertThatBalance(Is.GreaterThan(sellerInitialBalance), "Seller was not paid for storage.");
|
||||||
buyer.Marketplace.AssertThatBalance(Is.LessThan(buyerInitialBalance), "Buyer was not charged for storage.");
|
buyer.Marketplace.AssertThatBalance(Is.LessThan(buyerInitialBalance), "Buyer was not charged for storage.");
|
||||||
|
|
Loading…
Reference in New Issue