public override ServiceBlock GetBlockProposal(VoteProcess <ServiceBlock> voteProcess, ServiceBlock lastBlock, int revision) { var remove = new HashSet <long>(); var generator = new ServiceBlockGenerator(_coreChain, _serviceChain, _maintainChain, 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 ServiceTransaction) != TransactionResultTypes.Ok) { remove.Add(transaction.UniqueIdentifier); } } foreach (var item in remove) { _transactions.Remove(item); } } return(generator.GenerateBlock(voteProcess.LocalIssuer, revision)); }
public override bool CheckBlockProposal(VoteProcess <ServiceBlock> voteProcess, ServiceBlock block, ServiceBlock lastBlock, out HashSet <long> invalidTransactionIds) { var generator = new ServiceBlockGenerator(_coreChain, _serviceChain, _maintainChain, lastBlock); invalidTransactionIds = generator.CheckBlock(block); if (invalidTransactionIds.Count > 0) { return(false); } return(true); }
public async Task <bool> Start(string[] args, CancellationTokenSource quiteToken) { _quitToken = quiteToken; if (_quitToken.IsCancellationRequested) { return(false); } var dataPath = "heleusdata"; var genesis = false; var sync = false; var run = false; var init = false; var newChainConfig = false; if (args.Length == 1) { dataPath = args[0]; run = true; } else if (args.Length == 2) { dataPath = args[0]; var cmd = args[1]; if (cmd == "init") { init = true; } else if (cmd == "run") { run = true; } else if (cmd == "sync") { sync = true; } else if (cmd == "chainconfig") { newChainConfig = true; } else if (cmd == "genesis") { genesis = true; } else { Usage(); return(false); } } else { Usage(); return(false); } if ((run || sync) && !File.Exists(Path.Combine(dataPath, $"{nameof(NodeConfig).ToLower()}.txt"))) { Usage(); var dp = new DirectoryInfo(dataPath); Log.Error($"Data path {dp.FullName} not initalized.", this); return(false); } Storage = new Storage(dataPath); if (!Storage.IsWriteable) { Log.Fatal($"Data path {Storage.Root} is not writeable!", this); return(false); } if (genesis) { Storage.DeleteDirectory("cache"); Storage.DeleteDirectory("chains"); } PubSub = Log.PubSub = new PubSub(); Log.Write($"Starting Heleus Node (Version {Program.Version})."); Log.Trace($"PID {System.Diagnostics.Process.GetCurrentProcess().Id}"); Log.Write($"Data path is '{Storage.Root.FullName}'."); var config = Config.Load <NodeConfig>(Storage); Log.AddIgnoreList(config.LogIgnore); Log.LogLevel = config.LogLevel; if (Program.IsDebugging) { Log.LogLevel = LogLevels.Trace; } if (newChainConfig) { var chainConfig = Config.Load <ChainConfig>(Storage, true); //if (chainConfig.Chains.Count == 0) { Log.Write("Chain config generated."); chainConfig.Chains.Add(new ChainConfig.ChainInfo { ChainKeys = new List <ChainConfig.ChainKeyInfo> { new ChainConfig.ChainKeyInfo { ChainKey = string.Empty, ChainKeyPassword = string.Empty, AttachementKey = -1 } } }); Config.Save(chainConfig); } return(false); } if (init) { Log.Write("Config file generated."); return(false); } if (!genesis) { if (config.NetworkPublicKey.IsNullOrEmpty()) { Log.Write("Network key not set. Querying beacon nodes."); var beacons = config.BeaconNodes; foreach (var beacon in beacons) { Log.Write($"Querying beacon node {beacon}."); var client = new NodeClient(new Uri(beacon)); var nodeInfo = (await client.DownloadNodeInfo()).Data; if (nodeInfo != null) { config.NetworkPublicKey = nodeInfo.NetworkKey.HexString; Config.Save(config); Log.Write($"Network key set to {config.NetworkPublicKey}."); break; } } } if (config.NetworkPublicKey.IsNullOrEmpty()) { Log.Write("No valid network key found or set.", this); return(false); } } NodeConfiguration = new NodeConfiguration(config, Config.Load <CoreKeyConfig>(Storage, false), Config.Load <ChainConfig>(Storage, false)); Host = new Host(config); AttachementManager = new AttachementManager(this); ChainManager = new ChainManager(this); if (!await ChainManager.Initalize()) { return(false); } if (genesis) { var result = GenesisBlock.Generate(Storage); var blockData = new BlockData <CoreBlock>(result.Block, result.Signature); await ChainManager.Start(false); await ChainManager.CoreChain.BlockStorage.StoreBlock(blockData); ChainManager.ConsumeBlockData(blockData); Log.Write($"Genesis block and keys generated. Network public key: {result.NetworkPublicKey.HexString}."); var coreKeyConfig = Config.Load <CoreKeyConfig>(Storage); coreKeyConfig.Key = result.NetworkVoteKey.HexString; coreKeyConfig.Password = result.NetworkVotePassword; config.NetworkPublicKey = result.NetworkPublicKey.HexString; Config.Save(config); Config.Save(coreKeyConfig); await ChainManager.Stop(); await ChainManager.Start(true); if (result.ServiceTransactions.Count > 0) { foreach (var serviceTransactions in result.ServiceTransactions) { var chainId = serviceTransactions.Key; var transactions = serviceTransactions.Value; var serviceChain = ChainManager.GetServiceChain(chainId); var maintainChain = ChainManager.GetMaintainChain(chainId); if (serviceChain != null) { var generator = new ServiceBlockGenerator(ChainManager.CoreChain, serviceChain, maintainChain, null); foreach (var transaction in transactions) { generator.ConsumeTransaction(transaction); } var serviceBlock = generator.GenerateBlock(0, 0); var serviceBlockData = new BlockData <ServiceBlock>(serviceBlock, new BlockSignatures(serviceBlock)); await serviceChain.BlockStorage.StoreBlock(serviceBlockData); serviceChain.ConsumeBlockData(serviceBlockData); } } } await ChainManager.Stop(); return(false); } SyncManager = new SyncManager(this); await SyncManager.Start(); //if (!await SyncManager.Start()) // return false; if (sync) { Log.Write("Sync done."); return(false); } AttachementManager.Start(); Kademlia = new Kademlia(Storage, this); TransactionManager = new TransactionManager(this); CouncilManager = new CouncilManager(this); NodeServer = new NodeServer(this, config.MaxIncomingConnections, config.MaxOutgoingConnectoins); ClientServer = new ClientServer(this); if (Host.EnableRemoteServices) { ServiceServer = new ServiceServer(); } await(Host as Host).Start(this); return(true); }
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); } }