Beispiel #1
0
        internal DataAccount GetDataAccount(long accountId, bool newFromServiceChain = true)
        {
            if (_dataAccounts.TryGetValue(accountId, out var account))
            {
                return(account);
            }

            var data = _dataAccountStorage.GetBlockData(accountId);

            if (data == null)
            {
                if (newFromServiceChain)
                {
                    var serviceAccount = _serviceChain.GetServiceAccount(accountId);
                    if (serviceAccount != null)
                    {
                        lock (_lock)
                        {
                            if (!_dataAccounts.TryGetValue(accountId, out var dataAccount))
                            {
                                if (_serviceChain.ServiceAccountExists(accountId))
                                {
                                    dataAccount = new DataAccount(accountId);
                                    _dataAccounts[accountId] = dataAccount;
                                    _dataAccountStorage.AddEntry(accountId, dataAccount.ToByteArray());

                                    //TaskRunner.Run(_dataAccountStorage.Commit);
                                }
                            }

                            return(dataAccount);
                        }
                    }
                }
                return(null);
            }

            using (var unpacker = new Unpacker(data))
            {
                account = new DataAccount(unpacker);
                lock (_lock)
                {
                    if (_dataAccounts.TryGetValue(accountId, out var storedAccount))
                    {
                        return(storedAccount);
                    }

                    if (account.AccountId != accountId)
                    {
                        throw new Exception("Invalid data account data");
                    }

                    _dataAccounts[accountId] = account;
                }

                return(account);
            }
        }
        internal MaintainAccount GetMaintainAccount(long accountId, bool newFromServiceChain = true)
        {
            if (_maintainAccounts.TryGetValue(accountId, out var account))
            {
                return(account);
            }

            var data = _maintainAccountStorage.GetBlockData(accountId);

            if (data == null)
            {
                if (newFromServiceChain)
                {
                    var serviceAccount = ServiceChain.GetServiceAccount(accountId);
                    if (serviceAccount != null)
                    {
                        lock (_lock)
                        {
                            if (!_maintainAccounts.TryGetValue(accountId, out var maintainAccount))
                            {
                                if (ServiceChain.ServiceAccountExists(accountId))
                                {
                                    maintainAccount = new MaintainAccount(accountId);
                                    _maintainAccounts[accountId] = maintainAccount;
                                    _maintainAccountStorage.AddEntry(accountId, maintainAccount.ToByteArray());
                                }
                            }

                            return(maintainAccount);
                        }
                    }
                }
                return(null);
            }

            using (var unpacker = new Unpacker(data))
            {
                account = new MaintainAccount(unpacker);
                lock (_lock)
                {
                    if (_maintainAccounts.TryGetValue(accountId, out var storedAccount))
                    {
                        return(storedAccount);
                    }

                    if (account.AccountId != accountId)
                    {
                        throw new Exception("Invalid data account data");
                    }

                    _maintainAccounts[accountId] = account;
                }

                return(account);
            }
        }
        public TransactionResultTypes ConsumeTransaction(ServiceTransaction transaction, bool addExtraTime = false)
        {
            if (transaction.IsExpired(addExtraTime))
            {
                return(TransactionResultTypes.Expired);
            }

            var transactionResult = _serviceChain.BlockStorage.HistoryContainsTransactionOrRegistration(transaction);

            if (transactionResult != TransactionResultTypes.Ok)
            {
                return(transactionResult);
            }

            var accountId      = transaction.AccountId;
            var coreAccount    = _coreChain.GetCoreAccount(accountId);
            var serviceAccount = _serviceChain.GetServiceAccount(accountId);

            var type = transaction.TransactionType;

            switch (type)
            {
            case ServiceTransactionTypes.Join:

                var joinTransaction = (transaction as JoinServiceTransaction);
                var joinResult      = IsJoinValid(coreAccount, serviceAccount, joinTransaction);
                if (joinResult == TransactionResultTypes.Ok)
                {
                    if (_blockInfo.AddJoin(joinTransaction, serviceAccount, _serviceChain))
                    {
                        return(TransactionResultTypes.Ok);
                    }

                    return(TransactionResultTypes.BlockLimitExceeded);
                }

                return(joinResult);

            case ServiceTransactionTypes.Purchase:

                if (serviceAccount == null)
                {
                    return(TransactionResultTypes.InvalidServiceAccount);
                }

                var purchaseTransaction = (transaction as PurchaseServiceTransaction);
                var receiver            = _serviceChain.GetServiceAccount(purchaseTransaction.ReceiverAccountId);
                var purchaseResult      = IsPurchaseValid(coreAccount, receiver, _chainInfo, purchaseTransaction);
                if (purchaseResult == TransactionResultTypes.Ok)
                {
                    if (_blockInfo.AddPurchase(purchaseTransaction, serviceAccount, _serviceChain))
                    {
                        return(TransactionResultTypes.Ok);
                    }

                    return(TransactionResultTypes.BlockLimitExceeded);
                }

                return(purchaseResult);

            case ServiceTransactionTypes.RequestRevenue:

                if (serviceAccount == null)
                {
                    return(TransactionResultTypes.InvalidServiceAccount);
                }

                var maintainAccount = _maintainChain.GetMaintainAccount(accountId);
                if (maintainAccount == null)
                {
                    return(TransactionResultTypes.InvalidServiceAccount);
                }

                var revenueTransaction = transaction as RequestRevenueServiceTransaction;

                if (serviceAccount.TotalRevenuePayout != revenueTransaction.CurrentTotalRevenuePayout)
                {
                    return(TransactionResultTypes.RevenueAmoutInvalid);
                }

                if (revenueTransaction.PayoutAmount <= 0)
                {
                    return(TransactionResultTypes.RevenueAmoutInvalid);
                }

                var totalPayout = serviceAccount.TotalRevenuePayout + revenueTransaction.PayoutAmount;
                if (totalPayout > maintainAccount.TotalRevenue)
                {
                    return(TransactionResultTypes.RevenueAmoutInvalid);
                }

                if (_blockInfo.AddRevenue(revenueTransaction, serviceAccount, _serviceChain))
                {
                    return(TransactionResultTypes.Ok);
                }

                return(TransactionResultTypes.BlockLimitExceeded);

            case ServiceTransactionTypes.FeatureRequest:
            case ServiceTransactionTypes.Service:
                return(TransactionResultTypes.Ok);
            }

            return(TransactionResultTypes.InvalidTransaction);
        }