public async Task OrderQuantumTest(KeyPair clientKeyPair, KeyPair alphaKeyPair, ConnectionState state, Type excpectedException) { Global.AppState.State = ApplicationState.Ready; var clientConnection = new AuditorWebSocketConnection(new FakeWebSocket(), null) { ConnectionState = state }; var account = Global.AccountStorage.GetAccount(clientKeyPair); var orderEnvelope = new OrderRequest { Account = account?.Account.Id ?? 0 }.CreateEnvelope(); orderEnvelope.Sign(clientKeyPair); var orderQuantumEnvelope = new RequestQuantum { RequestEnvelope = orderEnvelope }.CreateEnvelope(); orderQuantumEnvelope.Sign(alphaKeyPair); await AssertMessageHandling(clientConnection, orderQuantumEnvelope, excpectedException); }
public async Task AccountDataRequestTest(int nonce, Type excpectedException) { context.AppState.State = ApplicationState.Ready; var accountWrapper = context.AccountStorage.GetAccount(TestEnvironment.Client1KeyPair); var order = new AccountDataRequest { Account = accountWrapper.Account.Id, RequestId = nonce, AccountWrapper = accountWrapper }; var envelope = order.CreateEnvelope(); envelope.Sign(TestEnvironment.Client1KeyPair); if (!context.IsAlpha) { var quantum = new RequestQuantum { Apex = context.QuantumStorage.CurrentApex + 1, RequestEnvelope = envelope, Timestamp = DateTime.UtcNow.Ticks }; envelope = quantum.CreateEnvelope(); envelope.Sign(TestEnvironment.AlphaKeyPair); } var res = await AssertQuantumHandling(envelope, excpectedException); if (excpectedException == null) { Assert.IsInstanceOf <Models.AccountDataResponse>(res); } }
public async Task OrderQuantumTest(KeyPair clientKeyPair, KeyPair alphaKeyPair, ConnectionState state, Type excpectedException) { context.AppState.State = ApplicationState.Ready; var clientConnection = new AuditorWebSocketConnection(context, new FakeAuditorConnectionInfo(new FakeWebSocket())) { ConnectionState = state }; var account = context.AccountStorage.GetAccount(clientKeyPair); var orderEnvelope = new OrderRequest { Account = account?.Account.Id ?? 0 }.CreateEnvelope().Sign(clientKeyPair); var orderQuantumEnvelope = new RequestQuantum { RequestEnvelope = orderEnvelope }.CreateEnvelope(); orderQuantumEnvelope.Sign(alphaKeyPair); using var writer = new XdrBufferWriter(); var inMessage = orderQuantumEnvelope.ToIncomingMessage(writer); await AssertMessageHandling(clientConnection, inMessage, excpectedException); }
void ValidateAccountRequestSignature(RequestQuantum request) { if (!(request.RequestEnvelope.IsSignedBy(request.RequestMessage.AccountWrapper.Account.Pubkey) && request.RequestEnvelope.AreSignaturesValid())) { throw new UnauthorizedAccessException("Request quantum has invalid signature."); } }
/// <summary> /// Process customer's order request. /// </summary> /// <param name="orderRequest">Order request quantum</param> /// <returns></returns> public void ExecuteOrder(EffectProcessorsContainer effectsContainer) { RequestQuantum orderRequestQuantum = (RequestQuantum)effectsContainer.Envelope.Message; var orderRequest = (OrderRequest)orderRequestQuantum.RequestEnvelope.Message; var updates = new OrderMatcher(orderRequest, effectsContainer).Match(); awaitedUpdates?.Add(updates); }
void ValidateAccountRequestRate(RequestQuantum request) { var account = request.RequestMessage.AccountWrapper; if (!account.RequestCounter.IncRequestCount(request.Timestamp, out string error)) { throw new TooManyRequestsException($"Request limit reached for account {account.Account.Pubkey}."); } }
MessageEnvelope GetQuantumEnvelope(MessageEnvelope envelope) { var quantumEnvelope = envelope; if (Global.IsAlpha && !(envelope.Message is Quantum))//we need to wrap client request { quantumEnvelope = new RequestQuantum { RequestEnvelope = envelope } }
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 void OrderbookPerformanceTest(int iterations, bool useNormalDistribution = false) { var rnd = new Random(); var testTradeResults = new Dictionary <RequestQuantum, EffectProcessorsContainer>(); for (var i = 1; i < iterations; i++) { var price = useNormalDistribution ? rnd.NextNormallyDistributed() + 50 : rnd.NextDouble() * 100; var accountWrapper = context.AccountStorage.GetAccount(account1.Account.Pubkey); var trade = new RequestQuantum { Apex = i, RequestEnvelope = new MessageEnvelope { Message = new OrderRequest { Account = accountWrapper.Account.Id, RequestId = i, Amount = rnd.Next(1, 20), Asset = 1, Price = Math.Round(price * 10) / 10, Side = rnd.NextDouble() >= 0.5 ? OrderSide.Buy : OrderSide.Sell, AccountWrapper = context.AccountStorage.GetAccount(account1.Account.Pubkey) }, Signatures = new List <Ed25519Signature>() }, Timestamp = DateTime.UtcNow.Ticks }; var diffObject = new DiffObject(); var conterOrderEffectsContainer = new EffectProcessorsContainer(context, trade.CreateEnvelope(), diffObject); testTradeResults.Add(trade, conterOrderEffectsContainer); } PerfCounter.MeasureTime(() => { foreach (var trade in testTradeResults) { context.Exchange.ExecuteOrder(trade.Value); } }, () => { var market = context.Exchange.GetMarket(1); return($"{iterations} iterations, orderbook size: {market.Bids.Count} bids, {market.Asks.Count} asks, {market.Bids.GetBestPrice().ToString("G3")}/{market.Asks.GetBestPrice().ToString("G3")} spread."); }); }
public async Task AccountRequestRateLimitTest(KeyPair clientKeyPair, int?requestLimit) { context.AppState.State = ApplicationState.Ready; var account = context.AccountStorage.GetAccount(clientKeyPair); if (requestLimit.HasValue) { account.Account.RequestRateLimits = new RequestRateLimits { HourLimit = (uint)requestLimit.Value, MinuteLimit = (uint)requestLimit.Value } } ; var minuteLimit = (account.Account.RequestRateLimits ?? context.Constellation.RequestRateLimits).MinuteLimit; var minuteIterCount = minuteLimit + 1; for (var i = 0; i < minuteIterCount; i++) { var envelope = new AccountDataRequest { Account = account.Account.Id, RequestId = i + 1, AccountWrapper = account }.CreateEnvelope(); envelope.Sign(clientKeyPair); if (!context.IsAlpha) { var quantum = new RequestQuantum { Apex = context.QuantumStorage.CurrentApex + 1, RequestEnvelope = envelope, Timestamp = DateTime.UtcNow.Ticks }; envelope = quantum.CreateEnvelope(); envelope.Sign(TestEnvironment.AlphaKeyPair); } if (i + 1 > minuteLimit) { await AssertQuantumHandling(envelope, typeof(TooManyRequestsException)); } else { await AssertQuantumHandling(envelope, null); } } }
public async Task WithdrawalQuantumTest(double amount, bool hasWithdrawal, bool useFakeSigner, Type excpectedException) { var outputStream = new XdrDataOutputStream(); var txBuilder = new TransactionBuilder(new AccountResponse(TestEnvironment.Client1KeyPair.AccountId, 1)); txBuilder.SetFee(10_000); txBuilder.AddOperation(new PaymentOperation.Builder(TestEnvironment.Client1KeyPair, new AssetTypeNative(), (amount / AssetsHelper.StroopsPerAsset).ToString("0.##########", CultureInfo.InvariantCulture)).SetSourceAccount(TestEnvironment.AlphaKeyPair).Build()); txBuilder.AddTimeBounds(new stellar_dotnet_sdk.TimeBounds(maxTime: DateTimeOffset.UtcNow.AddSeconds(60))); var tx = txBuilder.Build(); stellar_dotnet_sdk.xdr.Transaction.Encode(outputStream, tx.ToXdrV1()); var account = Global.AccountStorage.GetAccount(TestEnvironment.Client1KeyPair); var withdrawal = new WithdrawalRequest { Account = account.Account.Id, RequestId = 1, TransactionXdr = outputStream.ToArray(), AccountWrapper = account }; var envelope = withdrawal.CreateEnvelope(); envelope.Sign(useFakeSigner ? TestEnvironment.Client2KeyPair : TestEnvironment.Client1KeyPair); if (!Global.IsAlpha) { var quantum = new RequestQuantum { Apex = Global.QuantumStorage.CurrentApex + 1, RequestEnvelope = envelope, Timestamp = DateTime.UtcNow.Ticks }; envelope = quantum.CreateEnvelope(); envelope.Sign(TestEnvironment.AlphaKeyPair); } var result = await AssertQuantumHandling(envelope, excpectedException); if (excpectedException == null) { Assert.IsTrue(account.HasPendingWithdrawal); Assert.IsTrue(account.Account.GetBalance(0).Liabilities == amount); } }
public async Task OrderQuantumTest(int nonce, int asset, int amount, OrderSide side, Type excpectedException) { var accountWrapper = context.AccountStorage.GetAccount(TestEnvironment.Client1KeyPair); var order = new OrderRequest { Account = accountWrapper.Account.Id, RequestId = nonce, Amount = amount, Asset = asset, Price = 100, Side = side, AccountWrapper = accountWrapper }; var envelope = order.CreateEnvelope(); envelope.Sign(TestEnvironment.Client1KeyPair); if (!context.IsAlpha) { var quantum = new RequestQuantum { Apex = context.QuantumStorage.CurrentApex + 1, RequestEnvelope = envelope, Timestamp = DateTime.UtcNow.Ticks }; envelope = quantum.CreateEnvelope(); envelope.Sign(TestEnvironment.AlphaKeyPair); } var res = await AssertQuantumHandling(envelope, excpectedException); if (excpectedException == null) { var currentMarket = context.Exchange.GetMarket(asset); Assert.IsTrue(currentMarket != null); var requests = side == OrderSide.Buy ? currentMarket.Bids : currentMarket.Asks; Assert.AreEqual(1, requests.Count); } }
public async Task PaymentQuantumTest(long amount, bool useFakeSigner, Type excpectedException) { var account = context.AccountStorage.GetAccount(TestEnvironment.Client1KeyPair); var withdrawal = new PaymentRequest { Account = account.Account.Id, RequestId = 1, Asset = 0, Destination = TestEnvironment.Client2KeyPair, Amount = amount, AccountWrapper = account }; var envelope = withdrawal.CreateEnvelope(); envelope.Sign(useFakeSigner ? TestEnvironment.Client2KeyPair : TestEnvironment.Client1KeyPair); if (!context.IsAlpha) { var quantum = new RequestQuantum { Apex = context.QuantumStorage.CurrentApex + 1, RequestEnvelope = envelope, Timestamp = DateTime.UtcNow.Ticks }; envelope = quantum.CreateEnvelope(); envelope.Sign(TestEnvironment.AlphaKeyPair); } var expextedBalance = account.Account.GetBalance(0).Amount - amount; await AssertQuantumHandling(envelope, excpectedException); if (excpectedException == null) { Assert.AreEqual(account.Account.GetBalance(0).Amount, expextedBalance); } }
public async Task OrderCancellationQuantumTest(int asset, int amount, OrderSide side, int apexMod, bool useFakeSigner, Type excpectedException) { var acc = context.AccountStorage.GetAccount(TestEnvironment.Client1KeyPair); var order = new OrderRequest { Account = acc.Account.Id, RequestId = 1, Amount = amount, Asset = asset, Price = 100, Side = side, AccountWrapper = acc }; var envelope = order.CreateEnvelope().Sign(useFakeSigner ? TestEnvironment.Client2KeyPair : TestEnvironment.Client1KeyPair); if (!context.IsAlpha) { var quantum = new RequestQuantum { Apex = context.QuantumStorage.CurrentApex + 1, RequestEnvelope = envelope, Timestamp = DateTime.UtcNow.Ticks }; envelope = quantum.CreateEnvelope().Sign(TestEnvironment.AlphaKeyPair); } var submitResult = await AssertQuantumHandling(envelope, excpectedException); if (excpectedException != null) { return; } var apex = ((Quantum)submitResult.OriginalMessage.Message).Apex + apexMod; var orderCancellation = new OrderCancellationRequest { Account = acc.Account.Id, RequestId = 2, OrderId = OrderIdConverter.Encode((ulong)apex, asset, side), AccountWrapper = context.AccountStorage.GetAccount(TestEnvironment.Client1KeyPair) }; envelope = orderCancellation.CreateEnvelope().Sign(TestEnvironment.Client1KeyPair); if (!context.IsAlpha) { var quantum = new RequestQuantum { Apex = context.QuantumStorage.CurrentApex + 1, RequestEnvelope = envelope, Timestamp = DateTime.UtcNow.Ticks }; envelope = quantum.CreateEnvelope().Sign(TestEnvironment.AlphaKeyPair); } var cancelResult = await AssertQuantumHandling(envelope, excpectedException); if (excpectedException != null) { return; } var currentMarket = context.Exchange.GetMarket(asset); Assert.IsTrue(currentMarket != null); var requests = side == OrderSide.Buy ? currentMarket.Bids : currentMarket.Asks; Assert.AreEqual(requests.Count, 0); }
public async Task TxCommitQuantumTest(int cursor, int amount, int asset, Type excpectedException) { context.AppState.State = ApplicationState.Ready; long apex = context.QuantumStorage.CurrentApex; var client1StartBalanceAmount = (long)0; var account1 = context.AccountStorage.GetAccount(TestEnvironment.Client1KeyPair).Account; var clientAccountBalance = account1.GetBalance(asset); var withdrawalDest = KeyPair.Random(); var txHash = new byte[] { }; if (clientAccountBalance != null && amount > 0) { client1StartBalanceAmount = clientAccountBalance.Amount; context.Constellation.TryFindAssetSettings(asset, out var assetSettings); var account = new stellar_dotnet_sdk.Account(TestEnvironment.Client1KeyPair.AccountId, 1); var txBuilder = new TransactionBuilder(account); txBuilder.SetFee(10_000); txBuilder.AddTimeBounds(new stellar_dotnet_sdk.TimeBounds(DateTimeOffset.UtcNow, new TimeSpan(0, 5, 0))); txBuilder.AddOperation( new PaymentOperation.Builder(withdrawalDest, assetSettings.ToAsset(), Amount.FromXdr(amount).ToString()) .SetSourceAccount((KeyPair)context.Constellation.Vault) .Build() ); var tx = txBuilder.Build(); txHash = tx.Hash(); var txV1 = tx.ToXdrV1(); var txStream = new XdrDataOutputStream(); stellar_dotnet_sdk.xdr.Transaction.Encode(txStream, txV1); var accountWrapper = context.AccountStorage.GetAccount(TestEnvironment.Client1KeyPair); var withdrawal = new WithdrawalRequest { Account = accountWrapper.Account.Id, TransactionXdr = txStream.ToArray(), RequestId = DateTime.UtcNow.Ticks, AccountWrapper = accountWrapper }; MessageEnvelope quantum = withdrawal.CreateEnvelope(); quantum.Sign(TestEnvironment.Client1KeyPair); if (!context.IsAlpha) { quantum = new RequestQuantum { Apex = ++apex, RequestEnvelope = quantum, Timestamp = DateTime.UtcNow.Ticks }.CreateEnvelope(); quantum.Sign(TestEnvironment.AlphaKeyPair); } //create withdrawal await context.QuantumHandler.HandleAsync(quantum); } var depositAmount = new Random().Next(10, 1000); var ledgerNotification = new TxNotification { TxCursor = (uint)cursor, Payments = new List <PaymentBase> { new Deposit { Amount = depositAmount, Destination = TestEnvironment.Client1KeyPair, Asset = asset }, new Withdrawal { TransactionHash = txHash, PaymentResult = PaymentResults.Success } } }; var ledgerNotificationEnvelope = ledgerNotification.CreateEnvelope(); ledgerNotificationEnvelope.Sign(TestEnvironment.Auditor1KeyPair); var ledgerCommitEnv = new TxCommitQuantum { Source = ledgerNotificationEnvelope, Apex = ++apex }.CreateEnvelope(); if (!context.IsAlpha) { var msg = ((TxCommitQuantum)ledgerCommitEnv.Message); msg.Timestamp = DateTime.UtcNow.Ticks; ledgerCommitEnv = msg.CreateEnvelope().Sign(TestEnvironment.AlphaKeyPair); } await AssertQuantumHandling(ledgerCommitEnv, excpectedException); if (excpectedException == null) { Assert.AreEqual(context.TxCursorManager.TxCursor, ledgerNotification.TxCursor); Assert.AreEqual(account1.GetBalance(asset).Liabilities, 0); Assert.AreEqual(account1.GetBalance(asset).Amount, client1StartBalanceAmount - amount + depositAmount); //acc balance + deposit - withdrawal } }
private void ExecuteWithOrderbook(int iterations, bool useNormalDistribution, Action <Action> executor) { var rnd = new Random(); var market = Global.Exchange.GetMarket(1); var testTradeResults = new Dictionary <RequestQuantum, EffectProcessorsContainer>(); for (var i = 1; i < iterations; i++) { var price = useNormalDistribution ? rnd.NextNormallyDistributed() + 50 : rnd.NextDouble() * 100; var request = new OrderRequest { RequestId = i, Amount = rnd.Next(1, 20), Asset = 1, Price = Math.Round(price * 27) / 13 }; if (rnd.NextDouble() >= 0.5) { request.Account = account1.Id; request.AccountWrapper = account1; request.Side = OrderSide.Buy; } else { request.Account = account2.Id; request.AccountWrapper = account2; request.Side = OrderSide.Sell; } var trade = new RequestQuantum { Apex = i, RequestEnvelope = new MessageEnvelope { Message = request, Signatures = new List <Ed25519Signature>() }, Timestamp = DateTime.UtcNow.Ticks }; var diffObject = new DiffObject(); var conterOrderEffectsContainer = new EffectProcessorsContainer(trade.CreateEnvelope(), diffObject); testTradeResults.Add(trade, conterOrderEffectsContainer); } var xlmStartBalance = account1.Account.GetBalance(0).Amount + account2.Account.GetBalance(0).Amount; var assetStartBalance = account1.Account.GetBalance(1).Amount + account2.Account.GetBalance(1).Amount; executor(() => { foreach (var trade in testTradeResults) { Global.Exchange.ExecuteOrder(trade.Value); } }); //cleanup orders foreach (var account in new[] { account1, account2 }) { var activeOrders = Global.Exchange.OrderMap.GetAllAccountOrders(account); foreach (var order in activeOrders) { var decodedOrderId = OrderIdConverter.Decode(order.OrderId); new OrderRemovedEffectProccessor(new OrderRemovedEffect { OrderId = order.OrderId, Amount = order.Amount, QuoteAmount = order.QuoteAmount, Price = order.Price, Asset = decodedOrderId.Asset, AccountWrapper = account }, market.GetOrderbook(decodedOrderId.Side)).CommitEffect(); } } Assert.AreEqual(xlmStartBalance, account1.Account.GetBalance(0).Amount + account2.Account.GetBalance(0).Amount); Assert.AreEqual(assetStartBalance, account1.Account.GetBalance(1).Amount + account2.Account.GetBalance(1).Amount); Assert.AreEqual(0, account1.Account.GetBalance(0).Liabilities); Assert.AreEqual(0, account1.Account.GetBalance(1).Liabilities); Assert.AreEqual(0, account2.Account.GetBalance(0).Liabilities); Assert.AreEqual(0, account2.Account.GetBalance(1).Liabilities); }
public async Task WithdrawalCleanupQuantumTest(double amount, bool useFakeHash, Type excpectedException) { var outputStream = new XdrDataOutputStream(); var txBuilder = new TransactionBuilder(new AccountResponse(TestEnvironment.Client1KeyPair.AccountId, 1)); txBuilder.SetFee(10_000); txBuilder.AddOperation(new PaymentOperation.Builder(TestEnvironment.Client1KeyPair, new AssetTypeNative(), (amount / AssetsHelper.StroopsPerAsset).ToString("0.##########", CultureInfo.InvariantCulture)).SetSourceAccount(TestEnvironment.AlphaKeyPair).Build()); txBuilder.AddTimeBounds(new stellar_dotnet_sdk.TimeBounds(maxTime: DateTimeOffset.UtcNow.AddSeconds(60))); var tx = txBuilder.Build(); stellar_dotnet_sdk.xdr.Transaction.Encode(outputStream, tx.ToXdrV1()); var account = context.AccountStorage.GetAccount(TestEnvironment.Client1KeyPair); var acc = context.AccountStorage.GetAccount(TestEnvironment.Client1KeyPair); var withdrawal = new WithdrawalRequest { Account = acc.Account.Id, RequestId = 1, TransactionXdr = outputStream.ToArray(), AccountWrapper = account }; var envelope = withdrawal.CreateEnvelope(); envelope.Sign(TestEnvironment.Client1KeyPair); if (!context.IsAlpha) { var quantum = new RequestQuantum { Apex = context.QuantumStorage.CurrentApex + 1, RequestEnvelope = envelope, Timestamp = DateTime.UtcNow.Ticks }; envelope = quantum.CreateEnvelope(); envelope.Sign(TestEnvironment.AlphaKeyPair); } var result = await AssertQuantumHandling(envelope, null); if (result.Status != ResultStatusCodes.Success) { throw new Exception("Withdrawal creation failed."); } var cleanup = new WithrawalsCleanupQuantum { ExpiredWithdrawal = useFakeHash ? new byte[] { } : tx.Hash(), Apex = context.QuantumStorage.CurrentApex + 1 }; envelope = cleanup.CreateEnvelope(); if (!context.IsAlpha) { cleanup.Timestamp = DateTime.UtcNow.Ticks; envelope = cleanup.CreateEnvelope(); envelope.Sign(TestEnvironment.AlphaKeyPair); } await AssertQuantumHandling(envelope, excpectedException); if (excpectedException == null) { Assert.IsTrue(!account.HasPendingWithdrawal); Assert.AreEqual(account.Account.GetBalance(0).Liabilities, 0); } }
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)); }