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