コード例 #1
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));
        }