public async Task ScamQuantaTest(bool useFakeClient, bool useFakeAlpha, bool invalidBalance)
        {
            var environment = new IntegrationTestEnvironment();

            await environment.PrepareConstellation(3, 1);

            var clientPk      = environment.Clients.First();
            var client        = environment.AlphaWrapper.Context.AccountStorage.GetAccount(clientPk);
            var quantaStorage = environment.AlphaWrapper.Context.QuantumStorage;

            EnvironmentHelper.SetTestEnvironmentVariable();

            var amount = invalidBalance
                ? client.Account.Balances[0].Amount + 1
                : environment.AlphaWrapper.Context.Constellation.MinAllowedLotSize + 1;
            var sqamRequest = new OrderRequest
            {
                Account        = client.Id,
                AccountWrapper = client,
                Amount         = amount,
                Price          = 1,
                Asset          = 1,
                RequestId      = 1,
                Side           = OrderSide.Buy
            }.CreateEnvelope().Sign(useFakeClient ? KeyPair.Random() : clientPk);

            var apex           = quantaStorage.CurrentApex + 1;
            var requestQuantum = new RequestQuantum
            {
                Apex            = quantaStorage.CurrentApex + 1,
                EffectsHash     = new byte[] { },
                PrevHash        = quantaStorage.LastQuantumHash,
                RequestEnvelope = sqamRequest,
                Timestamp       = DateTime.UtcNow.Ticks
            }.CreateEnvelope().Sign(useFakeAlpha ? KeyPair.Random() : environment.AlphaWrapper.Settings.KeyPair);

            quantaStorage.AddQuantum(requestQuantum, requestQuantum.ComputeMessageHash());

            var expectedState = useFakeClient || useFakeAlpha || invalidBalance ? ApplicationState.Failed : ApplicationState.Ready;

            if (expectedState == ApplicationState.Ready)
            {
                await environment.AssertConstellationApex(apex, TimeSpan.FromSeconds(10));
            }

            await Task.WhenAll(environment.AuditorWrappers.Select(a => IntegrationTestEnvironmentExtensions.AssertState(a.Startup, expectedState, TimeSpan.FromSeconds(10))));
        }
        public async Task AlphaRestartWithQuantaDelayTest(bool invalidHash, bool invalidClientSignature, bool invalidAlphaSignature)
        {
            var environment = new IntegrationTestEnvironment();

            await environment.PrepareConstellation(1, 3);

            var lastApex = environment.AlphaWrapper.Context.QuantumStorage.CurrentApex;
            var lastHash = environment.AlphaWrapper.Context.QuantumStorage.LastQuantumHash;

            var clientPk = environment.Clients.First();
            var client   = environment.AlphaWrapper.Context.AccountStorage.GetAccount(clientPk);

            //wait while all auditors will process all available quanta
            await environment.AssertConstellationApex(lastApex, TimeSpan.FromSeconds(5));

            //generate quantum that will not be processed by Alpha
            var request = new AccountDataRequest
            {
                Account        = client.Id,
                RequestId      = DateTime.UtcNow.Ticks,
                AccountWrapper = client
            }
            .CreateEnvelope()
            .Sign(clientPk);

            var quantum = new RequestQuantum
            {
                Apex            = lastApex + 1,
                PrevHash        = lastHash,
                RequestEnvelope = request,
                Timestamp       = DateTime.UtcNow.Ticks
            };
            var quantumEnvelope = quantum
                                  .CreateEnvelope();

            var result = await environment.ProcessQuantumIsolated(quantumEnvelope);

            quantum.EffectsHash = result.effectsHash;
            quantumEnvelope.Sign(environment.AlphaWrapper.Settings.KeyPair);

            await environment.AlphaWrapper.Shutdown();

            await Task.WhenAll(environment.AuditorWrappers.Select(a => IntegrationTestEnvironmentExtensions.AssertState(a.Startup, ApplicationState.Running, TimeSpan.FromSeconds(10))));

            //handle quantum
            await Task.WhenAll(environment.AuditorWrappers.Select(a =>
            {
                var rawQuantum      = quantumEnvelope.ToByteArray();
                var auditorsQuantum = XdrConverter.Deserialize <MessageEnvelope>(rawQuantum);
                return(a.Context.QuantumHandler.HandleAsync(auditorsQuantum));
            }));

            //change quantum
            environment.AuditorWrappers.ForEach(a =>
            {
                a.Context.QuantumStorage.GetQuantaBacth(lastApex + 1, 1, out var quanta);
                var quantum = quanta.First();
                if (invalidHash)
                {
                    ((Quantum)quantum.Message).Timestamp = DateTime.UtcNow.Ticks;
                }
                if (invalidClientSignature)
                {
                    var request = (RequestQuantum)quantum.Message;
                    request.RequestEnvelope.Signatures.Clear();
                    request.RequestEnvelope.Sign(KeyPair.Random());
                }
                if (invalidAlphaSignature)
                {
                    quantum.Signatures.Clear();
                    quantum.Sign(KeyPair.Random());
                }
            });

            await environment.AlphaWrapper.Run();

            var expectedState = invalidHash || invalidClientSignature || invalidAlphaSignature ? ApplicationState.Failed : ApplicationState.Ready;

            await IntegrationTestEnvironmentExtensions.AssertState(environment.AlphaWrapper.Startup, expectedState, TimeSpan.FromSeconds(30));

            if (expectedState == ApplicationState.Failed)
            {
                return;
            }

            await Task.WhenAll(environment.AuditorWrappers.Select(a => IntegrationTestEnvironmentExtensions.AssertState(a.Startup, ApplicationState.Ready, TimeSpan.FromSeconds(10))));

            await environment.AssertConstellationApex(lastApex + 1, TimeSpan.FromSeconds(5));
        }