public void XdrReaderPerformanceTest(int rounds, int iterations) { var testArray = new byte[32]; Array.Fill(testArray, (byte)100); var stream = new XdrBufferWriter(); for (var i = 0; i < iterations; i++) { stream.WriteInt32(435); stream.WriteString("oiewurouqwe"); stream.WriteVariable(testArray); } var serialized = stream.ToArray(); PerfCounter.MeasureTime(() => { for (var r = 0; r < rounds; r++) { var reader = new XdrBufferReader(serialized); for (var i = 0; i < iterations; i++) { reader.ReadInt32(); reader.ReadString(); reader.ReadVariableAsSpan(); } } }, () => $"({rounds} rounds, {iterations} iterations)"); }
public static QuantumModel FromQuantumContainer(MessageEnvelope quantum, List <Effect> effects, int[] accounts, byte[] buffer) { if (quantum == null) { throw new ArgumentNullException(nameof(quantum)); } if (accounts == null) { throw new ArgumentNullException(nameof(accounts)); } if (effects == null) { throw new ArgumentNullException(nameof(effects)); } var quantumMessage = (Quantum)quantum.Message; using var writer = new XdrBufferWriter(buffer); XdrConverter.Serialize(new QuantumContainer { Quantum = quantum, Effects = effects }, writer); return(new QuantumModel { Apex = quantumMessage.Apex, Accounts = accounts, Bin = writer.ToArray() }); }
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); }
public async Task AuditorStateTest(KeyPair clientKeyPair, ConnectionState state, Type excpectedException) { context.AppState.State = ApplicationState.Rising; var clientConnection = new AlphaWebSocketConnection(context, new FakeWebSocket(), "127.0.0.1") { ClientPubKey = clientKeyPair.PublicKey, ConnectionState = state }; var envelope = new AuditorState { PendingQuanta = new List <MessageEnvelope>(), State = ApplicationState.Running }.CreateEnvelope(); envelope.Sign(clientKeyPair); using var writer = new XdrBufferWriter(); var inMessage = envelope.ToIncomingMessage(writer); await AssertMessageHandling(clientConnection, inMessage, excpectedException); if (excpectedException == null) { Assert.AreEqual(context.AppState.State, ApplicationState.Running); } }
public async Task AuditorPerfStatisticsTest() { var auditorPerf = new AuditorPerfStatistics { BatchInfos = new List <Models.BatchSavedInfo>(), QuantaPerSecond = 1, QuantaQueueLength = 2, UpdateDate = DateTime.UtcNow.Ticks }; var envelope = auditorPerf.CreateEnvelope(); envelope.Sign(TestEnvironment.Auditor1KeyPair); var auditorConnection = new AlphaWebSocketConnection(context, new FakeWebSocket(), "127.0.0.1") { ClientPubKey = TestEnvironment.Auditor1KeyPair }; using var writer = new XdrBufferWriter(); var inMessage = envelope.ToIncomingMessage(writer); await AssertMessageHandling(auditorConnection, inMessage, null); }
public async Task TxCommitQuantumTest(KeyPair alphaKeyPair, ConnectionState state, Type excpectedException) { context.AppState.State = ApplicationState.Ready; var clientConnection = new AuditorWebSocketConnection(context, new FakeAuditorConnectionInfo(new FakeWebSocket())) { ConnectionState = state }; var ledgerNotification = new TxNotification { TxCursor = 0, Payments = new List <PaymentBase>() }; var envelope = new TxCommitQuantum { Source = ledgerNotification.CreateEnvelope() }.CreateEnvelope(); envelope.Sign(alphaKeyPair); using var writer = new XdrBufferWriter(); var inMessage = envelope.ToIncomingMessage(writer); await AssertMessageHandling(clientConnection, inMessage, excpectedException); }
public static byte[] ToByteArray(this object objToSerialize, XdrBufferWriter writer) { var bytes = objToSerialize as byte[]; if (bytes != null) { return(bytes); } XdrConverter.Serialize(objToSerialize, writer); return(writer.ToArray()); }
public async Task AccountRequestRateLimitTest(KeyPair clientKeyPair, int?requestLimit) { context.AppState.State = ApplicationState.Ready; var account = context.AccountStorage.GetAccount(clientKeyPair); if (requestLimit.HasValue) { //TODO: replace it with quantum var effect = new RequestRateLimitUpdateEffect { Account = account.Id, AccountWrapper = account, RequestRateLimits = new RequestRateLimits { HourLimit = (uint)requestLimit.Value, MinuteLimit = (uint)requestLimit.Value } }; var effectProcessor = new RequestRateLimitUpdateEffectProcessor(effect, context.Constellation.RequestRateLimits); effectProcessor.CommitEffect(); } var clientConnection = new AlphaWebSocketConnection(context, new FakeWebSocket(), "127.0.0.1") { ClientPubKey = clientKeyPair, ConnectionState = ConnectionState.Ready, Account = account }; 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 }.CreateEnvelope(); envelope.Sign(clientKeyPair); using var writer = new XdrBufferWriter(); var inMessage = envelope.ToIncomingMessage(writer); if (i + 1 > minuteLimit) { await AssertMessageHandling(clientConnection, inMessage, typeof(TooManyRequestsException)); } else { await AssertMessageHandling(clientConnection, inMessage); } } }
/// <summary> /// Submit message to the constellation. /// </summary> /// <param name="envelope"></param> /// <returns></returns> public async Task <QuantumResult> SendMessage(MessageEnvelope envelope) { if (!envelope.IsSignedBy(Config.ClientKeyPair)) { envelope.Sign(Config.ClientKeyPair); } QuantumResult result = null; if (envelope.Message.MessageId != default) { result = new QuantumResult(envelope, ConstellationInfo); result.ScheduleExpiration(RequestTimeout); collator.Add(result); } using (var writerBuffer = Rent(1024)) { try { var writer = new XdrBufferWriter(writerBuffer.Buffer); XdrConverter.Serialize(envelope, writer); await sendMessageSemaphore.WaitAsync(); await webSocket.SendAsync(writerBuffer.Buffer.AsMemory(0, writer.Length), WebSocketMessageType.Binary, true, cancellationTokenSource.Token); } catch (WebSocketException e) { if (result != null) { result.SetException(e); } await CloseConnection(WebSocketCloseStatus.ProtocolError, e.Message); } catch (Exception e) { if (result == null) { throw; } result.SetException(e); } finally { sendMessageSemaphore.Release(); } } return(result); }
public static byte[] ComputeHash(this object objToSerialize) { var bytes = objToSerialize as byte[]; if (bytes != null) { return(SHA256.Create().ComputeHash(bytes)); } using var buffer = XdrBufferFactory.Rent(); using var writer = new XdrBufferWriter(buffer.Buffer); XdrConverter.Serialize(objToSerialize, writer); var hash = SHA256.Create().ComputeHash(buffer.Buffer, 0, writer.Length); return(hash); }
public async Task AlphaStateTest(ApplicationState alphaState) { context.AppState.State = ApplicationState.Running; var clientConnection = new AuditorWebSocketConnection(context, new FakeAuditorConnectionInfo(new FakeWebSocket())); var envelope = new AlphaState { State = alphaState }.CreateEnvelope().Sign(TestEnvironment.AlphaKeyPair); using var writer = new XdrBufferWriter(); var inMessage = envelope.ToIncomingMessage(writer); var isHandled = await context.MessageHandlers.HandleMessage(clientConnection, inMessage); Assert.IsTrue(isHandled); }
public async Task QuantaBatchTest(KeyPair alphaKeyPair, ConnectionState state, Type excpectedException) { context.AppState.State = ApplicationState.Ready; var clientConnection = new AuditorWebSocketConnection(context, new FakeAuditorConnectionInfo(new FakeWebSocket())) { ConnectionState = state }; var orderEnvelope = new QuantaBatch { Quanta = new List <MessageEnvelope>() }.CreateEnvelope(); orderEnvelope.Sign(alphaKeyPair); using var writer = new XdrBufferWriter(); var inMessage = orderEnvelope.ToIncomingMessage(writer); await AssertMessageHandling(clientConnection, inMessage, excpectedException); }
public async Task SetApexCursorTest(KeyPair clientKeyPair, ConnectionState state, Type excpectedException) { context.AppState.State = ApplicationState.Ready; var clientConnection = new AlphaWebSocketConnection(context, new FakeWebSocket(), "127.0.0.1") { ClientPubKey = clientKeyPair.PublicKey, ConnectionState = state }; var envelope = new SetApexCursor { Apex = 1 }.CreateEnvelope(); envelope.Sign(clientKeyPair); using var writer = new XdrBufferWriter(); var inMessage = envelope.ToIncomingMessage(writer); await AssertMessageHandling(clientConnection, inMessage, excpectedException); }
public virtual async Task SendMessage(MessageEnvelope envelope) { await sendMessageSemaphore.WaitAsync(); try { Global.ExtensionsManager.BeforeSendMessage(this, envelope); if (!envelope.IsSignedBy(Global.Settings.KeyPair.PublicKey)) { envelope.Sign(Global.Settings.KeyPair); } using var buffer = XdrBufferFactory.Rent(); using var writer = new XdrBufferWriter(buffer.Buffer); XdrConverter.Serialize(envelope, writer); if (webSocket == null) { throw new ObjectDisposedException(nameof(webSocket)); } if (webSocket.State == WebSocketState.Open) { await webSocket.SendAsync(buffer.AsSegment(0, writer.Length), WebSocketMessageType.Binary, true, cancellationToken); } Global.ExtensionsManager.AfterSendMessage(this, envelope); } catch (Exception exc) { if (exc is OperationCanceledException || exc is WebSocketException socketException && (socketException.WebSocketErrorCode == WebSocketError.InvalidState)) { return; } Global.ExtensionsManager.SendMessageFailed(this, envelope, exc); throw; } finally { sendMessageSemaphore.Release(); } }
/// <summary> /// Signs an envelope with a given <see cref="KeyPair"/> and appends the signature to the <see cref="MessageEnvelope.Signatures"/>. /// </summary> /// <param name="messageEnvelope">Envelope to sign</param> /// <param name="keyPair">Key pair to use for signing</param> /// <param name="buffer">Buffer to use for computing hash code.</param> public static MessageEnvelope Sign(this MessageEnvelope messageEnvelope, KeyPair keyPair, byte[] buffer) { if (messageEnvelope == null) { throw new ArgumentNullException(nameof(messageEnvelope)); } if (keyPair == null) { throw new ArgumentNullException(nameof(keyPair)); } if (buffer == null) { throw new ArgumentNullException(nameof(buffer)); } using var writer = new XdrBufferWriter(buffer); XdrConverter.Serialize(messageEnvelope.Message, writer); var signature = writer.ToArray().ComputeHash().Sign(keyPair); messageEnvelope.Signatures.Add(signature); return(messageEnvelope); }
public void HandshakeInvalidDataTest() { context.AppState.State = ApplicationState.Ready; var clientConnection = new AlphaWebSocketConnection(context, new FakeWebSocket(), "127.0.0.1"); var handshake = new HandshakeData(); handshake.Randomize(); var envelope = new HandshakeInit { HandshakeData = handshake }.CreateEnvelope(); envelope.Sign(TestEnvironment.Client1KeyPair); using var writer = new XdrBufferWriter(); var inMessage = envelope.ToIncomingMessage(writer); Assert.ThrowsAsync <ConnectionCloseException>(async() => await context.MessageHandlers.HandleMessage(clientConnection, inMessage)); }
public async Task TxNotificationTest(KeyPair clientKeyPair, ConnectionState state, Type excpectedException) { context.AppState.State = ApplicationState.Ready; var clientConnection = new AlphaWebSocketConnection(context, new FakeWebSocket(), "127.0.0.1") { ClientPubKey = clientKeyPair.PublicKey, ConnectionState = state }; var envelope = new TxNotification { TxCursor = context.TxCursorManager.TxCursor + 1, Payments = new List <PaymentBase>() }.CreateEnvelope(); envelope.Sign(clientKeyPair); using var writer = new XdrBufferWriter(); var inMessage = envelope.ToIncomingMessage(writer); await AssertMessageHandling(clientConnection, inMessage, excpectedException); }
public async Task AccountDataRequestTest(ConnectionState state, Type excpectedException) { context.AppState.State = ApplicationState.Ready; var clientConnection = new AlphaWebSocketConnection(context, new FakeWebSocket(), "127.0.0.1") { ClientPubKey = TestEnvironment.Client1KeyPair.PublicKey, ConnectionState = state }; var account = context.AccountStorage.GetAccount(TestEnvironment.Client1KeyPair); var envelope = new AccountDataRequest { Account = account.Account.Id, RequestId = 1 }.CreateEnvelope(); envelope.Sign(TestEnvironment.Client1KeyPair); using var writer = new XdrBufferWriter(); var inMessage = envelope.ToIncomingMessage(writer); await AssertMessageHandling(clientConnection, inMessage, excpectedException); }
public async Task HandshakeTest(KeyPair clientKeyPair, ApplicationState alphaState, Type expectedException) { context.AppState.State = alphaState; var clientConnection = new AlphaWebSocketConnection(context, new FakeWebSocket(), "127.0.0.1"); var message = new HandshakeInit { HandshakeData = clientConnection.HandshakeData }; var envelope = message.CreateEnvelope(); envelope.Sign(clientKeyPair); using var writer = new XdrBufferWriter(); var inMessage = envelope.ToIncomingMessage(writer); if (expectedException == null) { var isHandled = await context.MessageHandlers.HandleMessage(clientConnection, inMessage); Assert.IsTrue(isHandled); Assert.AreEqual(clientConnection.ClientPubKey, new RawPubKey(clientKeyPair.AccountId)); if (clientConnection.ClientPubKey.Equals((RawPubKey)TestEnvironment.Auditor1KeyPair)) { Assert.AreEqual(clientConnection.ConnectionState, ConnectionState.Validated); } else { Assert.AreEqual(clientConnection.ConnectionState, ConnectionState.Ready); } } else { Assert.ThrowsAsync(expectedException, async() => await context.MessageHandlers.HandleMessage(clientConnection, inMessage)); } }
public async Task EffectsRequestTest(KeyPair client, ConnectionState state, Type excpectedException) { context.AppState.State = ApplicationState.Ready; var account = context.AccountStorage.GetAccount(client); var clientConnection = new AlphaWebSocketConnection(context, new FakeWebSocket(), "127.0.0.1") { ClientPubKey = client, ConnectionState = state, Account = account }; var envelope = new EffectsRequest { Account = account.Account.Id, AccountWrapper = account }.CreateEnvelope(); envelope.Sign(client); using var writer = new XdrBufferWriter(); var inMessage = envelope.ToIncomingMessage(writer); await AssertMessageHandling(clientConnection, inMessage, excpectedException); }
public static IncomingMessage ToIncomingMessage(this MessageEnvelope envelope, XdrBufferWriter writer) { if (envelope == null) { throw new ArgumentNullException(nameof(envelope)); } XdrConverter.Serialize(envelope.Message, writer); var messageHash = writer.ToArray().ComputeHash(); return(new IncomingMessage(envelope, messageHash)); }
public static IncomingMessage ToIncomingMessage(this MessageEnvelope envelope, XdrBufferFactory.RentedBuffer rentedBuffer) { using var writer = new XdrBufferWriter(rentedBuffer.Buffer); return(envelope.ToIncomingMessage(writer)); }
public void XdrCompatibilityTest() { var testArray = new byte[32]; Array.Fill(testArray, (byte)100); //forward compatibility var legacyXdrSerializationStream = new XdrDataOutputStream(); legacyXdrSerializationStream.WriteInt(435); legacyXdrSerializationStream.WriteUInt(435); legacyXdrSerializationStream.WriteLong(43546345634657565L); legacyXdrSerializationStream.WriteDoubleArray(new double[] { 435.15, 64656.11 }); legacyXdrSerializationStream.WriteString("oiewurouqwe"); legacyXdrSerializationStream.WriteVarOpaque(32, testArray); var bufferReader = new XdrBufferReader(legacyXdrSerializationStream.ToArray()); Assert.AreEqual(435, bufferReader.ReadInt32()); Assert.AreEqual((uint)435, bufferReader.ReadUInt32()); Assert.AreEqual(43546345634657565L, bufferReader.ReadInt64()); { var length = bufferReader.ReadInt32(); var value = new double[length]; for (var i = 0; i < length; i++) { value[i] = bufferReader.ReadDouble(); } Assert.AreEqual(new double[] { 435.15, 64656.11 }, value); } Assert.AreEqual("oiewurouqwe", bufferReader.ReadString()); Assert.AreEqual(testArray, bufferReader.ReadVariable()); using var streamReader = new XdrStreamReader(new MemoryStream(legacyXdrSerializationStream.ToArray())); Assert.AreEqual(435, streamReader.ReadInt32()); Assert.AreEqual((uint)435, streamReader.ReadUInt32()); Assert.AreEqual(43546345634657565L, streamReader.ReadInt64()); { var length = streamReader.ReadInt32(); var value = new double[length]; for (var i = 0; i < length; i++) { value[i] = streamReader.ReadDouble(); } Assert.AreEqual(new double[] { 435.15, 64656.11 }, value); } Assert.AreEqual("oiewurouqwe", streamReader.ReadString()); Assert.AreEqual(testArray, streamReader.ReadVariable()); //backward compatibility var bufferWriter = new XdrBufferWriter(); bufferWriter.WriteInt32(435); bufferWriter.WriteUInt32((uint)435); { var arr = new double[] { 435.15, 64656.11 }; bufferWriter.WriteInt32(arr.Length); foreach (var d in arr) { bufferWriter.WriteDouble(d); } } bufferWriter.WriteString("oiewurouqwe"); bufferWriter.WriteVariable(testArray); var legacyXdrReader = new XdrDataInputStream(bufferWriter.ToArray()); Assert.AreEqual(435, legacyXdrReader.ReadInt()); Assert.AreEqual((uint)435, legacyXdrReader.ReadUInt()); Assert.AreEqual(new double[] { 435.15, 64656.11 }, legacyXdrReader.ReadDoubleArray()); Assert.AreEqual("oiewurouqwe", legacyXdrReader.ReadString()); Assert.AreEqual(testArray, legacyXdrReader.ReadVarOpaque(32)); using var memoryStream = new MemoryStream(); var streamWriter = new XdrStreamWriter(memoryStream); streamWriter.WriteInt32(435); streamWriter.WriteUInt32((uint)435); { var arr = new double[] { 435.15, 64656.11 }; streamWriter.WriteInt32(arr.Length); foreach (var d in arr) { streamWriter.WriteDouble(d); } } streamWriter.WriteString("oiewurouqwe"); streamWriter.WriteVariable(testArray); var res = memoryStream.ToArray(); var reference = bufferWriter.ToArray(); CollectionAssert.AreEqual(reference, res); }