Esempio n. 1
0
 public static Order ToOrder(this OrderModel order, AccountStorage accountStorage)
 {
     return(new Order
     {
         Amount = order.Amount,
         QuoteAmount = order.QuoteAmount,
         OrderId = unchecked ((ulong)order.Id),
         Price = order.Price,
         AccountWrapper = accountStorage.GetAccount(order.Account)
     });
 }
Esempio n. 2
0
        public static async Task Setup(Snapshot snapshot)
        {
            Constellation = snapshot.Settings;

            AccountStorage = new AccountStorage(snapshot.Accounts, Constellation.RequestRateLimits);

            if (Exchange != null)
            {
                Exchange.OnUpdates -= Exchange_OnUpdates;
                Exchange?.Dispose();
            }
            Exchange = Exchange.RestoreExchange(snapshot.Settings.Assets, snapshot.Orders, IsAlpha);

            WithdrawalStorage?.Dispose(); WithdrawalStorage = new WithdrawalStorage(snapshot.Withdrawals, (!EnvironmentHelper.IsTest && IsAlpha));

            TxCursorManager = new TxCursorManager(snapshot.TxCursor);

            TxListener?.Dispose(); TxListener = IsAlpha ? (TxListenerBase) new AlphaTxListener(snapshot.TxCursor) : new AuditorTxListener(snapshot.TxCursor);

            if (IsAlpha)
            {
                AuditLedgerManager?.Dispose(); AuditLedgerManager = new AuditLedgerManager();

                AuditResultManager?.Dispose(); AuditResultManager = new ResultManager();

                await DisposeAnalyticsManager();

                AnalyticsManager = new AnalyticsManager(
                    PermanentStorage,
                    DepthsSubscription.Precisions.ToList(),
                    Constellation.Assets.Where(a => !a.IsXlm).Select(a => a.Id).ToList(),
                    snapshot.Orders.Select(o => o.ToOrderInfo()).ToList()
                    );

                await AnalyticsManager.Restore(DateTime.UtcNow);

                AnalyticsManager.StartTimers();

                AnalyticsManager.OnError  += AnalyticsManager_OnError;
                AnalyticsManager.OnUpdate += AnalyticsManager_OnUpdate;
                Exchange.OnUpdates        += Exchange_OnUpdates;

                DisposePerformanceStatisticsManager();

                PerformanceStatisticsManager            = new PerformanceStatisticsManager();
                PerformanceStatisticsManager.OnUpdates += PerformanceStatisticsManager_OnUpdates;
            }

            ExtensionsManager?.Dispose(); ExtensionsManager = new ExtensionsManager();
            ExtensionsManager.RegisterAllExtensions();
        }
        public virtual Task Setup(Snapshot snapshot)
        {
            Constellation = snapshot.Settings;

            AccountStorage = new AccountStorage(snapshot.Accounts);

            Exchange?.Dispose(); Exchange = Exchange.RestoreExchange(snapshot.Settings.Assets, snapshot.Orders, IsAlpha, useLegacyOrderbook);

            WithdrawalStorage?.Dispose(); WithdrawalStorage = new WithdrawalStorage(snapshot.Withdrawals);

            TxCursorManager = new TxCursorManager(snapshot.TxCursor);

            return(Task.CompletedTask);
        }
Esempio n. 4
0
        private async Task <List <Order> > GetOrders(AccountStorage accountStorage)
        {
            var orderModels = await storage.LoadOrders();

            var orders      = new List <Order>();
            var orderLength = orderModels.Count;

            for (int i = 0; i < orderLength; i++)
            {
                orders.Add(orderModels[i].ToOrder(accountStorage));
            }

            return(orders);
        }
Esempio n. 5
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());
        }
        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);
        }
Esempio n. 7
0
        public static void TryAssignAccountWrapper(this MessageEnvelope envelope, AccountStorage accountStorage)
        {
            var requestMessage = default(RequestMessage);

            if (envelope.Message is RequestQuantum)
            {
                requestMessage = ((RequestQuantum)envelope.Message).RequestMessage;
            }
            else if (envelope.Message is RequestMessage)
            {
                requestMessage = (RequestMessage)envelope.Message;
            }
            else
            {
                return;
            }

            if (accountStorage == null)
            {
                throw new ArgumentNullException(nameof(accountStorage));
            }
            requestMessage.AccountWrapper = accountStorage.GetAccount(requestMessage.Account);
        }
 public AccountCreateEffectProcessor(AccountCreateEffect effect, AccountStorage accountStorage)
     : base(effect)
 {
     this.accountStorage = accountStorage ?? throw new ArgumentNullException(nameof(accountStorage));
 }
Esempio n. 9
0
 public AccountCreateEffectProcessor(AccountCreateEffect effect, AccountStorage accountStorage, RequestRateLimits requestRateLimits)
     : base(effect)
 {
     this.accountStorage    = accountStorage ?? throw new ArgumentNullException(nameof(accountStorage));
     this.requestRateLimits = requestRateLimits ?? throw new ArgumentNullException(nameof(requestRateLimits));
 }
 public static void AddAccountCreate(this EffectProcessorsContainer effectProcessors, AccountStorage accountStorage, int accountId, RawPubKey publicKey)
 {
     effectProcessors.Add(new AccountCreateEffectProcessor(
                              new AccountCreateEffect
     {
         Account = accountId,
         Pubkey  = publicKey,
         Apex    = effectProcessors.Apex
     },
                              accountStorage,
                              effectProcessors.Context.Constellation.RequestRateLimits
                              ));
 }
 public static void AddAccountCreate(this EffectProcessorsContainer effectProcessors, AccountStorage accountStorage, int accountId, RawPubKey publicKey)
 {
     effectProcessors.Add(new AccountCreateEffectProcessor(
                              new AccountCreateEffect
     {
         AccountId = accountId,
         Pubkey    = publicKey,
         Apex      = effectProcessors.Apex
     },
                              accountStorage
                              ));
 }
Esempio n. 12
0
        /// <summary>
        /// Builds snapshot for specified apex
        /// </summary>
        /// <param name="apex"></param>
        /// <returns></returns>
        public async Task <Snapshot> GetSnapshot(long apex)
        {
            if (apex < 0)
            {
                throw new ArgumentException("Apex cannot be less than zero.");
            }

            var lastApex = await GetLastApex();

            if (lastApex < apex)
            {
                throw new InvalidOperationException("Requested apex is greater than the last known one.");
            }

            //some auditors can have capped db
            var minRevertApex = await GetMinRevertApex();

            if (minRevertApex == -1 && apex != lastApex || apex < minRevertApex)
            {
                throw new InvalidOperationException($"Lack of data to revert to {apex} apex.");
            }

            var settings = await GetConstellationSettings(apex);

            if (settings == null)
            {
                return(null);
            }

            var stellarData = await storage.LoadConstellationState();

            var accounts = (await GetAccounts()).Select(a => new AccountWrapper(a, settings.RequestRateLimits));

            var accountStorage = new AccountStorage(accounts);

            var withdrawals = await GetWithdrawals(accountStorage, settings);

            var orders = await GetOrders(accountStorage);

            var exchange = await GetRestoredExchange(orders);

            var withdrawalsStorage = new WithdrawalStorage(withdrawals);

            var batchSize = 1000;
            var effects   = new List <Effect>();

            while (true)
            {
                var quanta = await storage.LoadQuantaAboveApex(apex, batchSize);

                effects.AddRange(quanta.SelectMany(q => q.ToQuantumContainer(accountStorage).Effects));
                if (quanta.Count < batchSize)
                {
                    break;
                }
            }

            for (var i = effects.Count - 1; i >= 0; i--)
            {
                var currentEffect = effects[i];
                var account       = currentEffect.AccountWrapper;
                IEffectProcessor <Effect> processor = null;
                switch (currentEffect)
                {
                case AccountCreateEffect accountCreateEffect:
                    processor = new AccountCreateEffectProcessor(accountCreateEffect, accountStorage, settings.RequestRateLimits);
                    break;

                case NonceUpdateEffect nonceUpdateEffect:
                    processor = new NonceUpdateEffectProcessor(nonceUpdateEffect);
                    break;

                case BalanceCreateEffect balanceCreateEffect:
                    processor = new BalanceCreateEffectProcessor(balanceCreateEffect);
                    break;

                case BalanceUpdateEffect balanceUpdateEffect:
                    processor = new BalanceUpdateEffectProcesor(balanceUpdateEffect);
                    break;

                case RequestRateLimitUpdateEffect requestRateLimitUpdateEffect:
                    processor = new RequestRateLimitUpdateEffectProcessor(requestRateLimitUpdateEffect, settings.RequestRateLimits);
                    break;

                case OrderPlacedEffect orderPlacedEffect:
                {
                    var orderBook = exchange.GetOrderbook(orderPlacedEffect.OrderId);
                    var order     = exchange.OrderMap.GetOrder(orderPlacedEffect.OrderId);
                    processor = new OrderPlacedEffectProcessor(orderPlacedEffect, orderBook, order);
                }
                break;

                case OrderRemovedEffect orderRemovedEffect:
                {
                    var orderBook = exchange.GetOrderbook(orderRemovedEffect.OrderId);
                    processor = new OrderRemovedEffectProccessor(orderRemovedEffect, orderBook);
                }
                break;

                case TradeEffect tradeEffect:
                {
                    var order = exchange.OrderMap.GetOrder(tradeEffect.OrderId);
                    if (order == null)         //no need to revert trade if no order was created
                    {
                        continue;
                    }
                    processor = new TradeEffectProcessor(tradeEffect, order);
                }
                break;

                case WithdrawalCreateEffect withdrawalCreate:
                {
                    var withdrawal = withdrawalsStorage.GetWithdrawal(withdrawalCreate.Apex);
                    processor = new WithdrawalCreateEffectProcessor(withdrawalCreate, withdrawal, withdrawalsStorage);
                }
                break;

                case WithdrawalRemoveEffect withdrawalRemove:
                {
                    var withdrawal = withdrawalsStorage.GetWithdrawal(withdrawalRemove.Apex);
                    processor = new WithdrawalRemoveEffectProcessor(withdrawalRemove, withdrawal, withdrawalsStorage);
                }
                break;

                default:
                    throw new NotImplementedException();
                }

                processor.RevertEffect();
            }

            var lastQuantumData = (await storage.LoadQuantum(apex)).ToQuantumContainer();

            //TODO: refactor restore exchange
            //we need to clean all order links to be able to restore exchange
            var allOrders = exchange.OrderMap.GetAllOrders();

            foreach (var order in orders)
            {
                order.Next = null;
                order.Prev = null;
            }

            return(new Snapshot
            {
                Apex = apex,
                Accounts = accountStorage.GetAll().OrderBy(a => a.Account.Id).ToList(),
                TxCursor = stellarData?.TxCursor ?? 0,
                Orders = allOrders.OrderBy(o => o.OrderId).ToList(),
                Settings = settings,
                Withdrawals = withdrawalsStorage.GetAll().OrderBy(w => w.Apex).ToList(),
                LastHash = lastQuantumData.Quantum.Message.ComputeHash()
            });
        }