public override CoreBlock GetBlockProposal(VoteProcess <CoreBlock> voteProcess, CoreBlock lastBlock, int revision) { var remove = new HashSet <long>(); var generator = new CoreBlockGenerator(_coreChain, lastBlock); lock (_lock) { foreach (var item in _transactions) { var transaction = item.Value; if (_blockStorage.HistoryContainsTransactionOrRegistration(transaction) != TransactionResultTypes.Ok) { remove.Add(transaction.UniqueIdentifier); continue; } if (generator.ConsumeTransaction(transaction as CoreTransaction) != TransactionResultTypes.Ok) { remove.Add(transaction.UniqueIdentifier); } } foreach (var item in remove) { _transactions.Remove(item); } } return(generator.GenerateBlock(voteProcess.LocalIssuer, revision)); }
async Task Loop() { while (!_node.HasQuit) { try { List <CoreItem> coreTransactions = null; List <ServiceItem> serviceTransactions = null; List <DataItem> dataTransactions = null; List <MaintainItem> maintainTransactions = null; lock (_lock) { if (_coreTransactions.Count > 0) { coreTransactions = _coreTransactions; _coreTransactions = new List <CoreItem>(); } if (_dataTransactions.Count > 0) { dataTransactions = _dataTransactions; _dataTransactions = new List <DataItem>(); } if (_serviceTransactions.Count > 0) { serviceTransactions = _serviceTransactions; _serviceTransactions = new List <ServiceItem>(); } if (_maintainTransactions.Count > 0) { maintainTransactions = _maintainTransactions; _maintainTransactions = new List <MaintainItem>(); } } if (coreTransactions != null) { var chain = _chainManager.CoreChain; var generator = new CoreBlockGenerator(chain, chain.BlockStorage.LastBlock as CoreBlock); foreach (var transactionItem in coreTransactions) { var transaction = transactionItem.Transaction; var sender = transactionItem.Sender; var nodeConnection = transactionItem.Connection as NodeConnection; var check = generator.ConsumeTransaction(transactionItem.Transaction); if (check == TransactionResultTypes.Ok) { if (!_node.CouncilManager.HandleNewTransaction(transaction, null, nodeConnection)) { _ = _node.NodeServer.Broadcast(new NodeTransactionMessage(transaction, sender == SenderTypes.Client ? 0 : (int)transactionItem.Payload) { SignKey = _configuration.LocaleNodePrivateKey }, new HashSet <NodeConnection> { nodeConnection }); } } else { if (sender == SenderTypes.Client) { var requestCode = transactionItem.Payload; if (requestCode != 0) { await transactionItem.Connection.Send(new ClientTransactionResponseMessage(requestCode, check, null) { SignKey = _configuration.LocaleNodePrivateKey }); } } } } } if (serviceTransactions != null) { var generators = new Dictionary <int, ServiceBlockGenerator>(); foreach (var transactionItem in serviceTransactions) { var transaction = transactionItem.Transaction; var sender = transactionItem.Sender; var chainid = transaction.TargetChainId; var serviceChain = _chainManager.GetServiceChain(chainid); var validationResult = await serviceChain.ValidateServiceTransaction(transaction); var result = validationResult.Result; var userCode = validationResult.UserCode; var message = validationResult.Message; if (result == TransactionResultTypes.Ok) { if (!generators.TryGetValue(chainid, out var generator)) { generator = new ServiceBlockGenerator(_chainManager.CoreChain, serviceChain, _chainManager.GetMaintainChain(chainid), serviceChain.BlockStorage.LastBlock as ServiceBlock); generators[chainid] = generator; } result = generator.ConsumeTransaction(transaction); } if (result == TransactionResultTypes.Ok) { _node.CouncilManager.HandleNewTransaction(transaction, null, transactionItem.Connection as NodeConnection); } else { if (sender == SenderTypes.Client) { var requestCode = transactionItem.Payload; if (requestCode != 0) { await transactionItem.Connection.Send(new ClientTransactionResponseMessage(requestCode, userCode, message, result, null) { SignKey = _configuration.LocaleNodePrivateKey }); } } } } } if (dataTransactions != null) { foreach (var transactionItem in dataTransactions) { var transaction = transactionItem.Transaction; var chainid = transaction.TargetChainId; var sender = transactionItem.Sender; var dataChain = _chainManager.GetDataChain(chainid, transaction.ChainIndex); var validation = transactionItem.NodeValidation; if (validation != null) { var chainKey = _node.ChainManager.CoreChain.GetChainInfo(chainid)?.GetValidChainKey(transaction.ChainIndex, validation.KeyIndex, transaction.Timestamp); if (!validation.IsValid(transaction, chainKey?.PublicKey)) { validation = null; } } if (validation != null) { _node.CouncilManager.HandleNewTransaction(transaction, validation, transactionItem.Connection as NodeConnection); } else { var validationResult = await dataChain.ValidateDataTransaction(transaction); validation = validationResult.TransactionValidation; var result = validationResult.Result; var userCode = validationResult.UserCode; var message = validationResult.Message; if (result == TransactionResultTypes.Ok) { _node.CouncilManager.HandleNewTransaction(transaction, validation, transactionItem.Connection as NodeConnection); } else { if (sender == SenderTypes.Client) { var requestCode = transactionItem.Payload; if (requestCode != 0) { await transactionItem.Connection.Send(new ClientTransactionResponseMessage(requestCode, userCode, message, result, null) { SignKey = _configuration.LocaleNodePrivateKey }); } } } } } } if (maintainTransactions != null) { var generators = new Dictionary <int, MaintainBlockGenerator>(); foreach (var item in maintainTransactions) { var transaction = item.Transaction; var chainId = transaction.TargetChainId; var chain = _chainManager.GetMaintainChain(chainId); var result = chain.ValidateMaintainTransaction(transaction); if (result == TransactionResultTypes.Ok) { if (!_node.CouncilManager.HandleNewTransaction(transaction, null, null)) { _ = _node.NodeServer.Broadcast(new NodeTransactionMessage(transaction, (int)item.Payload) { SignKey = _configuration.LocaleNodePrivateKey }, null); } } } } } catch (Exception ex) { Log.HandleException(ex, this); } await Task.Delay(50); } }