CoreAccount GetCoreAccount(long accountId)
        {
            if (_accounts.TryGetValue(accountId, out var account))
            {
                return(account);
            }

            account = _coreChain.GetCoreAccount(accountId, true, true);
            if (account == null)
            {
                return(null);
            }

            _accounts[account.AccountId] = account;
            return(account);
        }
Beispiel #2
0
        public async Task <TransactionValidationResult> ValidateDataTransaction(DataTransaction transaction)
        {
            var userCode = 0L;
            var result   = TransactionResultTypes.Unknown;
            var message  = string.Empty;
            TransactionValidation nodeValidation = null;

            var type      = transaction.TransactionType;
            var chainInfo = _coreChain.GetChainInfo(ChainId);
            var accountId = transaction.AccountId;
            var service   = _node.ChainManager.GetService(ChainId);

            if (chainInfo == null)
            {
                result = TransactionResultTypes.ChainNotFound;
                goto end;
            }

            if (service == null)
            {
                result = TransactionResultTypes.ChainServiceUnavailable;
                goto end;
            }

            if (!_chainKeyValid)
            {
                var chainKey = chainInfo.GetValidChainKey(ChainIndex, ChainKeyIndex, Time.Timestamp);
                if (chainKey == null || chainKey.PublicKey != ChainKey.PublicKey)
                {
                    result = TransactionResultTypes.ChainNodeInvalid;
                    goto end;
                }
                _chainKeyValid = true;
            }

            if (transaction == null)
            {
                result = TransactionResultTypes.InvalidTransaction;
                goto end;
            }

            if (!transaction.IsDataTransactionValid)
            {
                result = TransactionResultTypes.InvalidContent;
                goto end;
            }

            if (BlockStorage.History.ContainsTransactionIdentifier(transaction))
            {
                result = TransactionResultTypes.AlreadyProcessed;
                goto end;
            }

            var coreAccount = _coreChain.GetCoreAccount(accountId);

            if (coreAccount == null)
            {
                result = TransactionResultTypes.InvalidCoreAccount;
                goto end;
            }

            var serviceAccount = _serviceChain.GetServiceAccount(accountId);

            if (transaction.SignKeyIndex == Protocol.CoreAccountSignKeyIndex)
            {
                if (!transaction.IsSignatureValid(coreAccount.AccountKey, null))
                {
                    result = TransactionResultTypes.InvalidSignature;
                    goto end;
                }
            }
            else
            {
                if (serviceAccount == null)
                {
                    result = TransactionResultTypes.InvalidServiceAccount;
                    goto end;
                }

                var accountKey = serviceAccount.GetValidAccountKey(transaction.SignKeyIndex, transaction.Timestamp);
                if (accountKey == null)
                {
                    result = TransactionResultTypes.InvalidServiceAccountKey;
                    goto end;
                }

                if (accountKey.IsExpired())
                {
                    result = TransactionResultTypes.Expired;
                    goto end;
                }

                if (!transaction.IsSignatureValid(coreAccount.AccountKey, accountKey))
                {
                    result = TransactionResultTypes.InvalidSignature;
                    goto end;
                }
            }

            {
                var(featResult, featCode) = ValidateTransactionFeatures((ushort)DataTransactionTypes.FeatureRequest, transaction);
                if (featResult != TransactionResultTypes.Ok)
                {
                    result   = featResult;
                    userCode = featCode;
                    goto end;
                }
            }

            if (type == DataTransactionTypes.Attachement)
            {
                if (!Attachements.AreAttachementsUploaded(transaction as AttachementDataTransaction))
                {
                    result = TransactionResultTypes.AttachementsNotUploaded;
                    goto end;
                }
            }

            var purchaseRequired = transaction.GetFeature <RequiredPurchase>(RequiredPurchase.FeatureId);

            if (purchaseRequired != null && purchaseRequired.RequiredPurchaseType != PurchaseTypes.None)
            {
                if (!serviceAccount.HasRequiredTransactionPurchase(transaction, purchaseRequired))
                {
                    result = TransactionResultTypes.PurchaseRequired;
                    goto end;
                }
            }

            var validation = await service.IsDataTransactionValid(transaction);

            userCode = validation.UserCode;
            message  = validation.Message;

            if (!validation.IsOK)
            {
                if (validation.Result == ServiceResultTypes.PurchaseRequired)
                {
                    result = TransactionResultTypes.PurchaseRequired;
                }
                else
                {
                    result = TransactionResultTypes.ChainServiceErrorResponse;
                }
                goto end;
            }

            result         = TransactionResultTypes.Ok;
            nodeValidation = new TransactionValidation(transaction, ChainKeyIndex, ChainKey);
end:

            return(new TransactionValidationResult(result, userCode, message, nodeValidation));
        }
        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);
        }
Beispiel #4
0
        public async Task <TransactionValidationResult> ValidateServiceTransaction(ServiceTransaction transaction)
        {
            var userCode = 0L;
            var result   = TransactionResultTypes.Unknown;
            var message  = string.Empty;
            TransactionValidation nodeValidation = null;

            if (transaction == null)
            {
                result = TransactionResultTypes.InvalidTransaction;
                goto end;
            }

            var chainInfo = CoreChain.GetChainInfo(ChainId);
            var accountId = transaction.AccountId;
            var service   = _node.ChainManager.GetService(ChainId);

            if (chainInfo == null)
            {
                result = TransactionResultTypes.ChainNotFound;
                goto end;
            }

            if (service == null)
            {
                result = TransactionResultTypes.ChainServiceUnavailable;
                goto end;
            }

            if (!_chainKeyValid)
            {
                var chainKey = chainInfo.GetValidChainKey(ChainIndex, _chainKeyIndex, Time.Timestamp);
                if (chainKey == null || chainKey.PublicKey != _chainKey.PublicKey)
                {
                    result = TransactionResultTypes.ChainNodeInvalid;
                    goto end;
                }
                _chainKeyValid = true;
            }

            if (BlockStorage.History.ContainsTransactionIdentifier(transaction))
            {
                result = TransactionResultTypes.AlreadyProcessed;
                goto end;
            }

            var coreAccount = CoreChain.GetCoreAccount(accountId);

            if (coreAccount == null)
            {
                result = TransactionResultTypes.InvalidCoreAccount;
                goto end;
            }

            {
                var(featResult, featCode) = ValidateTransactionFeatures((ushort)ServiceTransactionTypes.FeatureRequest, transaction);
                if (featResult != TransactionResultTypes.Ok)
                {
                    result   = featResult;
                    userCode = featCode;

                    goto end;
                }
            }

            var validation = await service.IsServiceTransactionValid(transaction);

            userCode = validation.UserCode;
            message  = validation.Message;

            if (!validation.IsOK)
            {
                if (validation.Result == ServiceResultTypes.PurchaseRequired)
                {
                    result = TransactionResultTypes.PurchaseRequired;
                }
                else
                {
                    result = TransactionResultTypes.ChainServiceErrorResponse;
                }
                goto end;
            }

            result         = TransactionResultTypes.Ok;
            nodeValidation = new TransactionValidation(transaction, _chainKeyIndex, _chainKey);
end:

            return(new TransactionValidationResult(result, userCode, message, nodeValidation));
        }