コード例 #1
0
        public static Effect ToEffect(this AtomicEffectModel effectModel, AccountWrapper accountWrapper)
        {
            var effect = XdrConverter.Deserialize <Effect>(effectModel.RawEffect);

            effect.AccountWrapper = accountWrapper;
            return(effect);
        }
コード例 #2
0
        public void XdrPrimitiveTypesSerialization(PrimitiveTypes original)
        {
            var serialized = XdrConverter.Serialize(original);
            var rehydrated = XdrConverter.Deserialize <PrimitiveTypes>(serialized);

            rehydrated.Should().BeEquivalentTo(original, opt => opt.Excluding(d => d.NotSearialized), "deserialized object should match original");
        }
コード例 #3
0
        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()
            });
        }
コード例 #4
0
 public static MessageEnvelope ToMessageEnvelope(this QuantumModel quantum)
 {
     if (quantum == null)
     {
         throw new ArgumentNullException(nameof(quantum));
     }
     return(XdrConverter.Deserialize <MessageEnvelope>(quantum.RawQuantum));
 }
コード例 #5
0
 public static AtomicEffectModel FromEffect(this Effect effect, int index)
 {
     return(new AtomicEffectModel
     {
         ApexIndex = index,
         RawEffect = XdrConverter.Serialize(effect)
     });
 }
コード例 #6
0
        public static void Init()
        {
            var allTypes = typeof(TestDynamicSerializersInitializer).Assembly.GetTypes();

            foreach (var type in allTypes)
            {
                XdrConverter.RegisterSerializer(type);
            }
        }
コード例 #7
0
        public void AssetsNullValueSerializationTest()
        {
            var asset = new AssetSettings {
                Code = "XLM"
            };
            var rawData = XdrConverter.Serialize(asset);

            asset = XdrConverter.Deserialize <AssetSettings>(rawData);
            Assert.AreEqual(null, asset.Issuer);
        }
コード例 #8
0
        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));
        }
コード例 #9
0
        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());
        }
コード例 #10
0
        /// <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);
        }
コード例 #11
0
        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);
        }
コード例 #12
0
        public void XdrInheritanceSerialization()
        {
            var mammal = GenerateMammal();

            var serializedMammal = XdrConverter.Serialize(mammal);

            XdrConverter.Deserialize <Vertebrate>(serializedMammal).Should().BeEquivalentTo(mammal);
            XdrConverter.Deserialize <Tetrapod>(serializedMammal).Should().BeEquivalentTo(mammal);
            XdrConverter.Deserialize <Mammal>(serializedMammal).Should().BeEquivalentTo(mammal);

            var fish           = GenerateFish();
            var serializedFish = XdrConverter.Serialize(fish);

            XdrConverter.Deserialize <Vertebrate>(serializedFish).Should().BeEquivalentTo(fish);
            XdrConverter.Deserialize <Fish>(serializedFish).Should().BeEquivalentTo(fish);
        }
コード例 #13
0
        public void XdrPrimitiveTypesSerializationPerformance()
        {
            var iterations = 1_000_000;
            var original   = GeneratePrimitives().Skip(1).First();

            PerfCounter.MeasureTime(() =>
            {
                for (var i = 0; i < iterations; i++)
                {
                    var serialized = XdrConverter.Serialize(original);
                    var rehydrated = XdrConverter.Deserialize <PrimitiveTypes>(serialized);
                }
            }, () =>
            {
                return($"{typeof(PrimitiveTypes).Name} serialization - {iterations} iterations.");
            });
        }
コード例 #14
0
        public void XdrInheritanceSerializationPerformance()
        {
            var iterations = 1_000_000;
            var original   = GeneratePrimitives().First();
            var mammal     = GenerateMammal();

            PerfCounter.MeasureTime(() =>
            {
                for (var i = 0; i < iterations; i++)
                {
                    var serializedMammal = XdrConverter.Serialize(mammal);
                    XdrConverter.Deserialize <Vertebrate>(serializedMammal);
                }
            }, () =>
            {
                return($"Inheritance serialization - {iterations} iterations.");
            });
        }
コード例 #15
0
        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();
            }
        }
コード例 #16
0
        /// <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);
        }
コード例 #17
0
        private async Task <List <WithdrawalWrapper> > GetWithdrawals(AccountStorage accountStorage, ConstellationSettings constellationSettings)
        {
            var withdrawalApexes = accountStorage.GetAll().Where(a => a.Account.Withdrawal != default).Select(a => a.Account.Withdrawal).ToArray();

            if (withdrawalApexes.Length < 1)
            {
                return(new List <WithdrawalWrapper>());
            }
            var withdrawalQuanta = await storage.LoadQuanta(withdrawalApexes);

            var withdrawals = withdrawalQuanta
                              .Select(w =>
            {
                var withdrawalQuantum = XdrConverter.Deserialize <MessageEnvelope>(w.Bin);
                var withdrawalRequest = ((WithdrawalRequest)((RequestQuantum)withdrawalQuantum.Message).RequestMessage);
                withdrawalQuantum.TryAssignAccountWrapper(accountStorage);
                return(WithdrawalWrapperExtensions.GetWithdrawal(withdrawalQuantum, constellationSettings));
            });

            return(withdrawals.OrderBy(w => w.Apex).ToList());
        }
コード例 #18
0
        public void OrderSerializationTest()
        {
            var pubkey    = new byte[32];
            var signature = new byte[64];

            Array.Fill(pubkey, (byte)10);
            Array.Fill(signature, (byte)64);
            var original = new OrderRequest()
            {
                Account     = 1,
                Amount      = 2131231,
                RequestId   = 1,
                TimeInForce = TimeInForce.ImmediateOrCancel,
                Asset       = 5,
                Price       = 23423.4325
            };
            var message = new MessageEnvelope()
            {
                Message    = original,
                Signatures = new List <Ed25519Signature> {
                    new Ed25519Signature()
                    {
                        Signer = pubkey, Signature = signature
                    }
                }
            };
            var deserializedMessage = XdrConverter.Deserialize <MessageEnvelope>(XdrConverter.Serialize(message));
            var deserialized        = deserializedMessage.Message as OrderRequest;

            Assert.AreEqual(pubkey, deserializedMessage.Signatures[0].Signer.Data);
            Assert.AreEqual(signature, deserializedMessage.Signatures[0].Signature);
            Assert.AreEqual(original.Account, deserialized.Account);
            Assert.AreEqual(original.Amount, deserialized.Amount);
            Assert.AreEqual(original.TimeInForce, deserialized.TimeInForce);
            Assert.AreEqual(original.Asset, deserialized.Asset);
            Assert.AreEqual(original.Nonce, deserialized.Nonce);
            Assert.AreEqual(original.Price, deserialized.Price);
        }
コード例 #19
0
        public static QuantumModel FromQuantum(MessageEnvelope quantum)
        {
            if (quantum == null)
            {
                throw new ArgumentNullException(nameof(quantum));
            }
            var quantumMessage = (Quantum)quantum.Message;
            var account        = 0;

            if (quantumMessage is RequestQuantum requestQuantum)
            {
                account = requestQuantum.RequestMessage.Account;
            }

            return(new QuantumModel
            {
                Apex = quantumMessage.Apex,
                Account = account,
                RawQuantum = XdrConverter.Serialize(quantum),
                Type = (int)quantumMessage.MessageType,
                TimeStamp = quantumMessage.Timestamp
            });
        }
コード例 #20
0
        public static QuantumContainer ToQuantumContainer(this QuantumModel quantum, AccountStorage accountStorage = null)
        {
            if (quantum == null)
            {
                throw new ArgumentNullException(nameof(quantum));
            }

            var quantumContainer = XdrConverter.Deserialize <QuantumContainer>(quantum.Bin);

            if (accountStorage != null)
            {
                foreach (var effect in quantumContainer.Effects)
                {
                    if (effect.Account == 0)
                    {
                        continue;
                    }
                    effect.AccountWrapper = accountStorage.GetAccount(effect.Account);
                }
            }

            return(quantumContainer);
        }
コード例 #21
0
        /// <summary>
        /// Fetches all quanta where apex is greater than the specified one.
        /// </summary>
        /// <param name="apex"></param>
        /// <param name="count">Count of quanta to load. Loads all if equal or less than 0</param>
        /// <returns></returns>
        public async Task <List <MessageEnvelope> > GetQuantaAboveApex(long apex, int count = 0)
        {
            var quantaModels = await storage.LoadQuantaAboveApex(apex, count);

            return(quantaModels.OrderBy(q => q.Apex).Select(q => XdrConverter.Deserialize <MessageEnvelope>(q.Bin)).ToList());
        }
コード例 #22
0
        private async Task Listen()
        {
            try
            {
                while (webSocket.State != WebSocketState.Closed && webSocket.State != WebSocketState.Aborted && !cancellationTokenSource.Token.IsCancellationRequested)
                {
                    var messageType = await webSocket.GetWebsocketBuffer(readerBuffer, cancellationTokenSource.Token);

                    if (cancellationTokenSource.Token.IsCancellationRequested)
                    {
                        break;
                    }
                    //the client send close message
                    if (messageType == WebSocketMessageType.Close)
                    {
                        if (webSocket.State != WebSocketState.CloseReceived)
                        {
                            continue;
                        }

                        await sendMessageSemaphore.WaitAsync();

                        try
                        {
                            await webSocket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "Close", CancellationToken.None);
                        }
                        finally
                        {
                            sendMessageSemaphore.Release();
                            cancellationTokenSource.Cancel();
                        }
                        continue;
                    }
                    try
                    {
                        var envelope = XdrConverter.Deserialize <MessageEnvelope>(new XdrBufferReader(readerBuffer.Buffer));
                        OnMessage.Invoke(envelope);
                    }
                    catch
                    {
                        OnException?.Invoke(new UnexpectedMessageException("Failed to deserialize a response message received from the server."));
                    }
                }
            }
            catch (OperationCanceledException)
            { }
            catch (Exception e)
            {
                var status = WebSocketCloseStatus.InternalServerError;
                //connection has been already closed by the other side
                if ((e as WebSocketException)?.WebSocketErrorCode == WebSocketError.ConnectionClosedPrematurely)
                {
                    return;
                }

                string errorDescription = null;
                if (e is ConnectionCloseException closeException)
                {
                    status           = closeException.Status;
                    errorDescription = closeException.Description;
                }
                else if (e is FormatException)
                {
                    status = WebSocketCloseStatus.ProtocolError;
                }
                else
                {
                    logger.Error(e);
                }

                await CloseConnection(status, errorDescription);
            }
            finally
            {
                _ = Task.Factory.StartNew(() => OnClose?.Invoke());
            }
        }
コード例 #23
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));
        }
コード例 #24
0
        public async Task <MessageEnvelope> GetQuantum(long apex)
        {
            var quantumModel = await storage.LoadQuantum(apex);

            return(XdrConverter.Deserialize <MessageEnvelope>(quantumModel.Bin));
        }
コード例 #25
0
        public async Task Listen()
        {
            try
            {
                while (webSocket.State != WebSocketState.Closed && webSocket.State != WebSocketState.Aborted && !cancellationToken.IsCancellationRequested)
                {
                    var result = await webSocket.GetWebsocketBuffer(MaxMessageSize, cancellationToken);

                    using (result.messageBuffer)
                        if (!cancellationToken.IsCancellationRequested)
                        {
                            //the client send close message
                            if (result.messageType == WebSocketMessageType.Close)
                            {
                                if (webSocket.State != WebSocketState.CloseReceived)
                                {
                                    continue;
                                }
                                await sendMessageSemaphore.WaitAsync();

                                try
                                {
                                    var timeoutTokenSource = new CancellationTokenSource(1000);
                                    await webSocket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "Close", CancellationToken.None);
                                }
                                finally
                                {
                                    sendMessageSemaphore.Release();
                                    cancellationTokenSource.Cancel();
                                }
                            }
                            else
                            {
                                MessageEnvelope envelope = null;
                                try
                                {
                                    var reader = new XdrBufferReader(result.messageBuffer.Buffer, result.messageBuffer.Length);
                                    envelope = XdrConverter.Deserialize <MessageEnvelope>(reader);

                                    if (!await HandleMessage(envelope))
                                    {
                                        throw new UnexpectedMessageException($"No handler registered for message type {envelope.Message.MessageType}.");
                                    }
                                }
                                catch (BaseClientException exc)
                                {
                                    Global.ExtensionsManager.HandleMessageFailed(this, envelope, exc);

                                    var statusCode = exc.GetStatusCode();

                                    //prevent recursive error sending
                                    if (!(envelope == null || envelope.Message is ResultMessage))
                                    {
                                        _ = SendMessage(envelope.CreateResult(statusCode));
                                    }
                                    if (statusCode == ResultStatusCodes.InternalError || !Global.IsAlpha)
                                    {
                                        logger.Error(exc);
                                    }
                                }
                            }
                        }
                }
            }
            catch (OperationCanceledException) { }
            catch (Exception e)
            {
                Global.ExtensionsManager.HandleMessageFailed(this, null, e);
                var closureStatus = WebSocketCloseStatus.InternalServerError;
                var desc          = default(string);
                if (e is WebSocketException webSocketException &&
                    webSocketException.WebSocketErrorCode == WebSocketError.ConnectionClosedPrematurely)    //connection already closed by the other side
                {
                    return;
                }