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); }
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); }
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)); }